summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/scanners/php/html+php_faulty.expected.raydebug1
-rw-r--r--test/scanners/php/html+php_faulty.in.php1
-rw-r--r--test/scanners/php/pleac.expected.raydebug5516
-rw-r--r--test/scanners/php/pleac.in.php5516
-rw-r--r--test/scanners/php/suite.rb2
-rw-r--r--test/scanners/php/test.expected.raydebug498
-rw-r--r--test/scanners/php/test.in.php498
-rw-r--r--test/scanners/sql/create_tables.expected.raydebug94
-rw-r--r--test/scanners/sql/create_tables.in.sql94
-rw-r--r--test/scanners/sql/maintenance.expected.raydebug24
-rw-r--r--test/scanners/sql/maintenance.in.sql24
-rw-r--r--test/scanners/sql/reference.expected.raydebug109
-rw-r--r--test/scanners/sql/reference.in.sql109
-rw-r--r--test/scanners/sql/selects.expected.raydebug46
-rw-r--r--test/scanners/sql/selects.in.sql46
-rw-r--r--test/scanners/sql/suite.rb2
16 files changed, 12580 insertions, 0 deletions
diff --git a/test/scanners/php/html+php_faulty.expected.raydebug b/test/scanners/php/html+php_faulty.expected.raydebug
new file mode 100644
index 0000000..11a0372
--- /dev/null
+++ b/test/scanners/php/html+php_faulty.expected.raydebug
@@ -0,0 +1 @@
+operator(<)operator(?)ident(php)
diff --git a/test/scanners/php/html+php_faulty.in.php b/test/scanners/php/html+php_faulty.in.php
new file mode 100644
index 0000000..b3d9bbc
--- /dev/null
+++ b/test/scanners/php/html+php_faulty.in.php
@@ -0,0 +1 @@
+<?php
diff --git a/test/scanners/php/pleac.expected.raydebug b/test/scanners/php/pleac.expected.raydebug
new file mode 100644
index 0000000..3bec15e
--- /dev/null
+++ b/test/scanners/php/pleac.expected.raydebug
@@ -0,0 +1,5516 @@
+comment(# -*- php -*-)
+comment(# The examples are taken from the Perl Cookbook)
+comment(# By Tom Christiansen & Nathan Torkington)
+comment(# see http://www.oreilly.com/catalog/cookbook for more)
+
+comment(# @@PLEAC@@_NAME)
+comment(# @@SKIP@@ PHP)
+
+comment(# @@PLEAC@@_WEB)
+comment(# @@SKIP@@ http://php.net/)
+
+comment(# @@PLEAC@@_1.0)
+comment(#-----------------------------)
+local_variable($string) operator(=) delimiter(')string(\\)string(n)delimiter(')operator(;) comment(# two characters, \\ and an n)
+local_variable($string) operator(=) delimiter(')string(Jon )char(\\')string(Maddog)char(\\')string( Orwant)delimiter(')operator(;) comment(# literal single quotes)
+local_variable($string) operator(=) delimiter(')string(Jon "Maddog" Orwant)delimiter(')operator(;) comment(# literal double quotes)
+comment(#-----------------------------)
+local_variable($string) operator(=) delimiter(")char(\\n)delimiter(")operator(;) comment(# a "newline" character)
+local_variable($string) operator(=) delimiter(")string(Jon )char(\\")string(Maddog)char(\\")string( Orwant)delimiter(")operator(;) comment(# literal double quotes)
+local_variable($string) operator(=) delimiter(")string(Jon 'Maddog' Orwant)delimiter(")operator(;) comment(# literal single quotes)
+comment(#-----------------------------)
+local_variable($a) operator(=)
+delimiter(")string(This is a multiline)
+string(here document)delimiter(")operator(;)
+
+local_variable($a) operator(=) delimiter(<<<EOF)
+constant(This) ident(is) ident(a) ident(multiline) ident(here) ident(document)
+ident(terminated) ident(by) constant(EOF) ident(on) ident(a) ident(line) ident(by) ident(itself)
+constant(EOF)operator(;)
+comment(#-----------------------------)
+
+comment(# @@PLEAC@@_1.1)
+comment(#-----------------------------)
+local_variable($value) operator(=) ident(substr)operator(()local_variable($string)operator(,) local_variable($offset)operator(,) local_variable($count)operator(\))operator(;)
+local_variable($value) operator(=) ident(substr)operator(()local_variable($string)operator(,) local_variable($offset)operator(\))operator(;)
+
+local_variable($string) operator(=) ident(substr_replace)operator(()local_variable($string)operator(,) local_variable($newstring)operator(,) local_variable($offset)operator(,) local_variable($count)operator(\))operator(;)
+local_variable($string) operator(=) ident(substr_replace)operator(()local_variable($string)operator(,) local_variable($newtail)operator(,) local_variable($offset)operator(\))operator(;)
+comment(#-----------------------------)
+comment(# get a 5-byte string, skip 3, then grab 2 8-byte strings, then the rest)
+pre_type(list)operator(()local_variable($leading)operator(,) local_variable($s1)operator(,) local_variable($s2)operator(,) local_variable($trailing)operator(\)) operator(=)
+ ident(array_values)operator(()ident(unpack)operator(()delimiter(")string(A5a/x3/A8b/A8c/A*d)delimiter(")operator(,) local_variable($data)operator(\))operator(;)
+
+comment(# split at five byte boundaries)
+ident(preg_match_all) operator(()delimiter(")string(/.)string({)string(5}/)delimiter(")operator(,) local_variable($data)operator(,) local_variable($f)operator(,) constant(PREG_PATTERN_ORDER)operator(\))operator(;)
+local_variable($fivers) operator(=) local_variable($f)operator([)integer(0)operator(])operator(;)
+
+comment(# chop string into individual characters)
+local_variable($chars) operator(=) local_variable($string)operator(;)
+comment(#-----------------------------)
+local_variable($string) operator(=) delimiter(")string(This is what you have)delimiter(")operator(;)
+comment(# +012345678901234567890 Indexing forwards (left to right\))
+comment(# 109876543210987654321- Indexing backwards (right to left\))
+comment(# note that 0 means 10 or 20, etc. above)
+
+local_variable($first) operator(=) ident(substr)operator(()local_variable($string)operator(,) integer(0)operator(,) integer(1)operator(\))operator(;) comment(# "T")
+local_variable($start) operator(=) ident(substr)operator(()local_variable($string)operator(,) integer(5)operator(,) integer(2)operator(\))operator(;) comment(# "is")
+local_variable($rest) operator(=) ident(substr)operator(()local_variable($string)operator(,) integer(13)operator(\))operator(;) comment(# "you have")
+local_variable($last) operator(=) ident(substr)operator(()local_variable($string)operator(,) integer(-1)operator(\))operator(;) comment(# "e")
+local_variable($end) operator(=) ident(substr)operator(()local_variable($string)operator(,) integer(-4)operator(\))operator(;) comment(# "have")
+local_variable($piece) operator(=) ident(substr)operator(()local_variable($string)operator(,) integer(-8)operator(,) integer(3)operator(\))operator(;) comment(# "you")
+comment(#-----------------------------)
+local_variable($string) operator(=) delimiter(")string(This is what you have)delimiter(")operator(;)
+pre_type(print) local_variable($string)operator(;)
+comment(#This is what you have)
+
+local_variable($string) operator(=) ident(substr_replace)operator(()local_variable($string)operator(,) delimiter(")string(wasn't)delimiter(")operator(,) integer(5)operator(,) integer(2)operator(\))operator(;) comment(# change "is" to "wasn't")
+comment(#This wasn't what you have)
+
+local_variable($string) operator(=) ident(substr_replace)operator(()local_variable($string)operator(,) delimiter(")string(ondrous)delimiter(")operator(,) integer(-12)operator(\))operator(;) comment(# "This wasn't wondrous")
+comment(#This wasn't wondrous)
+
+local_variable($string) operator(=) ident(substr_replace)operator(()local_variable($string)operator(,) delimiter(")delimiter(")operator(,) integer(0)operator(,) integer(1)operator(\))operator(;) comment(# delete first character)
+comment(#his wasn't wondrous)
+
+local_variable($string) operator(=) ident(substr_replace)operator(()local_variable($string)operator(,) delimiter(")delimiter(")operator(,) integer(-10)operator(\))operator(;) comment(# delete last 10 characters)
+comment(#his wasn')
+comment(#-----------------------------)
+reserved(if) operator(()ident(preg_match)operator(()delimiter(")string(/pattern/)delimiter(")operator(,) ident(substr)operator(()local_variable($string)operator(,) integer(-10)operator(\))operator(\)) operator({)
+ pre_type(print) delimiter(")string(Pattern matches in last 10 characters)char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(# substitute "at" for "is", restricted to first five characters)
+local_variable($string)operator(=)operator(()ident(substr_replace)operator(()ident(preg_replace)operator(()delimiter(")string(/is/)delimiter(")operator(,) delimiter(")string(at)delimiter(")operator(,) ident(substr)operator(()local_variable($string)operator(,)integer(0)operator(,)integer(5)operator(\))operator(\))operator(,)integer(0)operator(,)integer(5)operator(\))operator(;)
+comment(#-----------------------------)
+comment(# exchange the first and last letters in a string)
+local_variable($a) operator(=) delimiter(")string(make a hat)delimiter(")operator(;)
+pre_type(list)operator(()local_variable($a)operator([)integer(0)operator(])operator(,) local_variable($a)operator([)ident(strlen)operator(()local_variable($a)operator(\))integer(-1)operator(])operator(\)) operator(=) constant(Array)operator(()ident(substr)operator(()local_variable($a)operator(,)integer(-1)operator(\))operator(,) ident(substr)operator(()local_variable($a)operator(,)integer(0)operator(,)integer(1)operator(\))operator(\))operator(;)
+pre_type(print) local_variable($a)operator(;)
+
+comment(#-----------------------------)
+comment(# extract column with unpack)
+local_variable($a) operator(=) delimiter(")string(To be or not to be)delimiter(")operator(;)
+local_variable($b) operator(=) ident(unpack)operator(()delimiter(")string(x6/A6a)delimiter(")operator(,) local_variable($a)operator(\))operator(;) comment(# skip 6, grab 6)
+pre_type(print) local_variable($b)operator([)delimiter(')string(a)delimiter(')operator(])operator(;)
+
+
+local_variable($b) operator(=) ident(unpack)operator(()delimiter(")string(x6/A2b/X5/A2c)delimiter(")operator(,) local_variable($a)operator(\))operator(;) comment(# forward 6, grab 2; backward 5, grab 2)
+pre_type(print) local_variable($b)operator([)delimiter(')string(b)delimiter(')operator(])operator(.)delimiter(")char(\\n)delimiter(")operator(.)local_variable($b)operator([)delimiter(')string(c)delimiter(')operator(])operator(.)delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(#-----------------------------)
+pre_type(function) ident(cut2fmt)operator(()operator(\)) operator({)
+ local_variable($positions) operator(=) ident(func_get_args)operator(()operator(\))operator(;)
+ local_variable($template) operator(=) delimiter(')delimiter(')operator(;)
+ local_variable($lastpos) operator(=) integer(1)operator(;)
+ reserved(foreach)operator(()local_variable($positions) reserved(as) local_variable($place)operator(\)) operator({)
+ local_variable($template) operator(.)operator(=) delimiter(")string(A)delimiter(") operator(.) operator(()local_variable($place) operator(-) local_variable($lastpos)operator(\)) operator(.) delimiter(")string( )delimiter(")operator(;)
+ local_variable($lastpos) operator(=) local_variable($place)operator(;)
+ operator(})
+ local_variable($template) operator(.)operator(=) delimiter(")string(A*)delimiter(")operator(;)
+ reserved(return) local_variable($template)operator(;)
+operator(})
+
+local_variable($fmt) operator(=) ident(cut2fmt)operator(()integer(8)operator(,) integer(14)operator(,) integer(20)operator(,) integer(26)operator(,) integer(30)operator(\))operator(;)
+pre_type(print) delimiter(")local_variable($fmt)char(\\n)delimiter(")operator(;)
+comment(#A7 A6 A6 A6 A4 A*)
+comment(#-----------------------------)
+
+comment(# @@PLEAC@@_1.2)
+comment(#-----------------------------)
+comment(# use $b if $b is true, else $c)
+local_variable($a) operator(=) local_variable($b)operator(?)local_variable($b)operator(:)local_variable($c)operator(;)
+
+comment(# set $x to $y unless $x is already true)
+local_variable($x) operator(|)operator(|) local_variable($x)operator(=)local_variable($y)operator(;)
+comment(#-----------------------------)
+comment(# use $b if $b is defined, else $c)
+local_variable($a) operator(=) ident(defined)operator(()local_variable($b)operator(\)) operator(?) local_variable($b) operator(:) local_variable($c)operator(;)
+comment(#-----------------------------)
+local_variable($foo) operator(=) local_variable($bar) operator(|)operator(|) local_variable($foo) operator(=) delimiter(")string(DEFAULT VALUE)delimiter(")operator(;)
+comment(#-----------------------------)
+local_variable($dir) operator(=) ident(array_shift)operator(()local_variable($_SERVER)operator([)delimiter(')string(argv)delimiter(')operator(])operator(\)) operator(|)operator(|) local_variable($dir) operator(=) delimiter(")string(/tmp)delimiter(")operator(;)
+comment(#-----------------------------)
+local_variable($dir) operator(=) local_variable($_SERVER)operator([)delimiter(')string(argv)delimiter(')operator(])operator([)integer(0)operator(]) operator(|)operator(|) local_variable($dir) operator(=) delimiter(")string(/tmp)delimiter(")operator(;)
+comment(#-----------------------------)
+local_variable($dir) operator(=) ident(defined)operator(()local_variable($_SERVER)operator([)delimiter(')string(argv)delimiter(')operator(])operator([)integer(0)operator(])operator(\)) operator(?) ident(array_shift)operator(()local_variable($_SERVER)operator([)delimiter(')string(argv)delimiter(')operator(])operator(\)) operator(:) delimiter(")string(/tmp)delimiter(")operator(;)
+comment(#-----------------------------)
+local_variable($dir) operator(=) ident(count)operator(()local_variable($_SERVER)operator([)delimiter(')string(argv)delimiter(')operator(])operator(\)) operator(?) local_variable($_SERVER)operator([)delimiter(')string(argv)delimiter(')operator(])operator([)integer(0)operator(]) operator(:) delimiter(")string(/tmp)delimiter(")operator(;)
+comment(#-----------------------------)
+local_variable($count)operator([)local_variable($shell)operator(?)local_variable($shell)operator(:)delimiter(")string(/bin/sh)delimiter(")operator(])operator(++)operator(;)
+comment(#-----------------------------)
+comment(# find the user name on Unix systems)
+local_variable($user) operator(=) local_variable($_ENV)operator([)delimiter(')string(USER)delimiter(')operator(])
+ operator(|)operator(|) local_variable($user) operator(=) local_variable($_ENV)operator([)delimiter(')string(LOGNAME)delimiter(')operator(])
+ operator(|)operator(|) local_variable($user) operator(=) ident(posix_getlogin)operator(()operator(\))
+ operator(|)operator(|) local_variable($user) operator(=) ident(posix_getpwuid)operator(()ident(posix_getuid)operator(()operator(\))operator(\))operator([)integer(0)operator(])
+ operator(|)operator(|) local_variable($user) operator(=) delimiter(")string(Unknown uid number )string($)string(<)delimiter(")operator(;)
+comment(#-----------------------------)
+local_variable($starting_point) operator(|)operator(|) local_variable($starting_point) operator(=) delimiter(")string(Greenwich)delimiter(")operator(;)
+comment(#-----------------------------)
+ident(count)operator(()local_variable($a)operator(\)) operator(|)operator(|) local_variable($a) operator(=) local_variable($b)operator(;) comment(# copy only if empty)
+local_variable($a) operator(=) ident(count)operator(()local_variable($b)operator(\)) operator(?) local_variable($b) operator(:) local_variable($c)operator(;) comment(# assign @b if nonempty, else @c)
+comment(#-----------------------------)
+
+comment(# @@PLEAC@@_1.3)
+comment(#-----------------------------)
+pre_type(list)operator(()local_variable($VAR1)operator(,) local_variable($VAR2)operator(\)) operator(=) pre_type(array)operator(()local_variable($VAR2)operator(,) local_variable($VAR1)operator(\))operator(;)
+comment(#-----------------------------)
+local_variable($temp) operator(=) local_variable($a)operator(;)
+local_variable($a) operator(=) local_variable($b)operator(;)
+local_variable($b) operator(=) local_variable($temp)operator(;)
+comment(#-----------------------------)
+local_variable($a) operator(=) delimiter(")string(alpha)delimiter(")operator(;)
+local_variable($b) operator(=) delimiter(")string(omega)delimiter(")operator(;)
+pre_type(list)operator(()local_variable($a)operator(,) local_variable($b)operator(\)) operator(=) pre_type(array)operator(()local_variable($b)operator(,) local_variable($a)operator(\))operator(;) comment(# the first shall be last -- and versa vice)
+comment(#-----------------------------)
+pre_type(list)operator(()local_variable($alpha)operator(,) local_variable($beta)operator(,) local_variable($production)operator(\)) operator(=) constant(Array)operator(()delimiter(")string(January)delimiter(")operator(,)delimiter(")string(March)delimiter(")operator(,)delimiter(")string(August)delimiter(")operator(\))operator(;)
+comment(# move beta to alpha,)
+comment(# move production to beta,)
+comment(# move alpha to production)
+pre_type(list)operator(()local_variable($alpha)operator(,) local_variable($beta)operator(,) local_variable($production)operator(\)) operator(=) pre_type(array)operator(()local_variable($beta)operator(,) local_variable($production)operator(,) local_variable($alpha)operator(\))operator(;)
+comment(#-----------------------------)
+
+comment(# @@PLEAC@@_1.4)
+comment(#-----------------------------)
+local_variable($num) operator(=) ident(ord)operator(()local_variable($char)operator(\))operator(;)
+local_variable($char) operator(=) ident(chr)operator(()local_variable($num)operator(\))operator(;)
+comment(#-----------------------------)
+local_variable($char) operator(=) ident(sprintf)operator(()delimiter(")string(%c)delimiter(")operator(,) local_variable($num)operator(\))operator(;) comment(# slower than chr($num\))
+ident(printf)operator(()delimiter(")string(Number %d is character %c)char(\\n)delimiter(")operator(,) local_variable($num)operator(,) local_variable($num)operator(\))operator(;)
+comment(#-----------------------------)
+local_variable($ASCII) operator(=) ident(unpack)operator(()delimiter(")string(C*)delimiter(")operator(,) local_variable($string)operator(\))operator(;)
+pre_type(eval)operator(()delimiter(')string($STRING = pack("C*", )delimiter(')operator(.)ident(implode)operator(()delimiter(')string(,)delimiter(')operator(,)local_variable($ASCII)operator(\))operator(.)delimiter(')string(\);)delimiter(')operator(\))operator(;)
+comment(#-----------------------------)
+local_variable($ascii_value) operator(=) ident(ord)operator(()delimiter(")string(e)delimiter(")operator(\))operator(;) comment(# now 101)
+local_variable($character) operator(=) ident(chr)operator(()integer(101)operator(\))operator(;) comment(# now "e")
+comment(#-----------------------------)
+ident(printf)operator(()delimiter(")string(Number %d is character %c)char(\\n)delimiter(")operator(,) integer(101)operator(,) integer(101)operator(\))operator(;)
+comment(#-----------------------------)
+local_variable($ascii_character_numbers) operator(=) ident(unpack)operator(()delimiter(")string(C*)delimiter(")operator(,) delimiter(")string(sample)delimiter(")operator(\))operator(;)
+pre_type(print) ident(explode)operator(()delimiter(")string( )delimiter(")operator(,)local_variable($ascii_character_numbers)operator(\))operator(.)delimiter(")char(\\n)delimiter(")operator(;)
+
+pre_type(eval)operator(()delimiter(')string($word = pack("C*", )delimiter(')operator(.)ident(implode)operator(()delimiter(')string(,)delimiter(')operator(,)local_variable($ascii_character_numbers)operator(\))operator(.)delimiter(')string(\);)delimiter(')operator(\))operator(;)
+local_variable($word) operator(=) ident(pack)operator(()delimiter(")string(C*)delimiter(")operator(,) integer(115)operator(,) integer(97)operator(,) integer(109)operator(,) integer(112)operator(,) integer(108)operator(,) integer(101)operator(\))operator(;) comment(# same)
+pre_type(print) delimiter(")local_variable($word)char(\\n)delimiter(")operator(;)
+comment(#-----------------------------)
+local_variable($hal) operator(=) delimiter(")string(HAL)delimiter(")operator(;)
+local_variable($ascii) operator(=) ident(unpack)operator(()delimiter(")string(C*)delimiter(")operator(,) local_variable($hal)operator(\))operator(;)
+reserved(foreach) operator(()local_variable($ascii) reserved(as) local_variable($val)operator(\)) operator({)
+ local_variable($val)operator(++)operator(;) comment(# add one to each ASCII value)
+operator(})
+pre_type(eval)operator(()delimiter(')string($ibm = pack("C*", )delimiter(')operator(.)ident(implode)operator(()delimiter(')string(,)delimiter(')operator(,)local_variable($ascii)operator(\))operator(.)delimiter(')string(\);)delimiter(')operator(\))operator(;)
+pre_type(print) delimiter(")local_variable($ibm)char(\\n)delimiter(")operator(;) comment(# prints "IBM")
+comment(#-----------------------------)
+
+comment(# @@PLEAC@@_1.5)
+comment(#-----------------------------)
+comment(// using perl regexp)
+local_variable($array) operator(=) ident(preg_split)operator(()delimiter(')string(//)delimiter(')operator(,) local_variable($string) operator(,)integer(-1)operator(,) constant(PREG_SPLIT_NO_EMPTY)operator(\))operator(;)
+comment(// using PHP function: $array = str_split($string\);)
+
+comment(// Cannot use unpack with a format of 'U*' in PHP.)
+comment(#-----------------------------)
+reserved(for) operator(()local_variable($offset) operator(=) integer(0)operator(;) ident(preg_match)operator(()delimiter(')string(/(.\)/)delimiter(')operator(,) local_variable($string)operator(,) local_variable($matches)operator(,) integer(0)operator(,) local_variable($offset)operator(\)) operator(>) integer(0)operator(;) local_variable($offset)operator(++)operator(\)) operator({)
+ comment(// $matches[1] has charcter, ord($matches[1]\) its number)
+operator(})
+comment(#-----------------------------)
+local_variable($seen) operator(=) pre_type(array)operator(()operator(\))operator(;)
+local_variable($string) operator(=) delimiter(")string(an apple a day)delimiter(")operator(;)
+reserved(foreach) operator(()ident(str_split)operator(()local_variable($string)operator(\)) reserved(as) local_variable($char)operator(\)) operator({)
+ local_variable($seen)operator([)local_variable($char)operator(]) operator(=) integer(1)operator(;)
+operator(})
+local_variable($keys) operator(=) ident(array_keys)operator(()local_variable($seen)operator(\))operator(;)
+ident(sort)operator(()local_variable($keys)operator(\))operator(;)
+pre_type(print) delimiter(")string(unique chars are: )delimiter(") operator(.) ident(implode)operator(()delimiter(')delimiter(')operator(,) local_variable($keys)operator(\))operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+ident(unique) ident(chars) label(are)operator(:) ident(adelnpy)
+comment(#-----------------------------)
+local_variable($seen) operator(=) pre_type(array)operator(()operator(\))operator(;)
+local_variable($string) operator(=) delimiter(")string(an apple a day)delimiter(")operator(;)
+reserved(for) operator(()local_variable($offset) operator(=) integer(0)operator(;) ident(preg_match)operator(()delimiter(')string(/(.\)/)delimiter(')operator(,) local_variable($string)operator(,) local_variable($matches)operator(,) integer(0)operator(,) local_variable($offset)operator(\)) operator(>) integer(0)operator(;) local_variable($offset)operator(++)operator(\)) operator({)
+ local_variable($seen)operator([)local_variable($matches)operator([)integer(1)operator(])operator(]) operator(=) integer(1)operator(;)
+operator(})
+local_variable($keys) operator(=) ident(array_keys)operator(()local_variable($seen)operator(\))operator(;)
+ident(sort)operator(()local_variable($keys)operator(\))operator(;)
+pre_type(print) delimiter(")string(unique chars are: )delimiter(") operator(.) ident(implode)operator(()delimiter(')delimiter(')operator(,) local_variable($keys)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+ident(unique) ident(chars) label(are)operator(:) ident(adelnpy)
+comment(#-----------------------------)
+local_variable($sum) operator(=) integer(0)operator(;)
+reserved(foreach) operator(()ident(unpack)operator(()delimiter(")string(C*)delimiter(")operator(,) local_variable($string)operator(\)) reserved(as) local_variable($byteval)operator(\)) operator({)
+ local_variable($sum) operator(+)operator(=) local_variable($byteval)operator(;)
+operator(})
+pre_type(print) delimiter(")string(sum is )local_variable($sum)char(\\n)delimiter(")operator(;)
+comment(// prints "1248" if $string was "an apple a day")
+comment(#-----------------------------)
+local_variable($sum) operator(=) ident(array_sum)operator(()ident(unpack)operator(()delimiter(")string(C*)delimiter(")operator(,) local_variable($string)operator(\))operator(\))operator(;)
+comment(#-----------------------------)
+
+comment(// sum - compute 16-bit checksum of all input files)
+local_variable($handle) operator(=) operator(@)ident(fopen)operator(()local_variable($argv)operator([)integer(1)operator(])operator(,) delimiter(')string(r)delimiter(')operator(\))operator(;)
+local_variable($checksum) operator(=) integer(0)operator(;)
+reserved(while) operator(()operator(!)ident(feof)operator(()local_variable($handle)operator(\))operator(\)) operator({)
+ local_variable($checksum) operator(+)operator(=) operator(()ident(array_sum)operator(()ident(unpack)operator(()delimiter(")string(C*)delimiter(")operator(,) ident(fgets)operator(()local_variable($handle)operator(\))operator(\))operator(\))operator(\))operator(;)
+operator(})
+local_variable($checksum) operator(%)operator(=) ident(pow)operator(()integer(2)operator(,)integer(16)operator(\)) operator(-) integer(1)operator(;)
+pre_type(print) delimiter(")local_variable($checksum)char(\\n)delimiter(")operator(;)
+
+comment(# @@INCLUDE@@ include/php/slowcat.php)
+comment(#-----------------------------)
+
+comment(# @@PLEAC@@_1.6)
+comment(#-----------------------------)
+local_variable($revchars) operator(=) ident(strrev)operator(()local_variable($string)operator(\))operator(;)
+comment(#-----------------------------)
+local_variable($revwords) operator(=) ident(implode)operator(()delimiter(")string( )delimiter(")operator(,) ident(array_reverse)operator(()ident(explode)operator(()delimiter(")string( )delimiter(")operator(,) local_variable($string)operator(\))operator(\))operator(\))operator(;)
+comment(#-----------------------------)
+comment(// reverse word order)
+local_variable($string) operator(=) delimiter(')string(Yoda said, "can you see this?")delimiter(')operator(;)
+local_variable($allwords) operator(=) ident(explode)operator(()delimiter(")string( )delimiter(")operator(,) local_variable($string)operator(\))operator(;)
+local_variable($revwords) operator(=) ident(implode)operator(()delimiter(")string( )delimiter(")operator(,) ident(array_reverse)operator(()local_variable($allwords)operator(\))operator(\))operator(;)
+pre_type(print) local_variable($revwords) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+ident(this)operator(?)delimiter(")string( see you )delimiter(")ident(can) ident(said)operator(,) constant(Yoda)
+comment(#-----------------------------)
+local_variable($revwords) operator(=) ident(implode)operator(()delimiter(")string( )delimiter(")operator(,) ident(array_reverse)operator(()ident(explode)operator(()delimiter(")string( )delimiter(")operator(,) local_variable($string)operator(\))operator(\))operator(\))operator(;)
+comment(#-----------------------------)
+local_variable($revwords) operator(=) ident(implode)operator(()delimiter(")string( )delimiter(")operator(,) ident(array_reverse)operator(()ident(preg_split)operator(()delimiter(")string(/()string(\\)string(s+\)/)delimiter(")operator(,) local_variable($string)operator(\))operator(\))operator(\))operator(;)
+comment(#-----------------------------)
+local_variable($word) operator(=) delimiter(")string(reviver)delimiter(")operator(;)
+local_variable($is_palindrome) operator(=) operator(()local_variable($word) operator(===) ident(strrev)operator(()local_variable($word)operator(\))operator(\))operator(;)
+comment(#-----------------------------)
+comment(// quite a one-liner since "php" does not have a -n switch)
+operator(%) ident(php) operator(-)ident(r) delimiter(')string(while (!feof(STDIN\)\) { $word = rtrim(fgets(STDIN\)\); if ($word == strrev($word\) && strlen($word\) > 5\) print $word; })delimiter(') operator(<) operator(/)ident(usr)operator(/)ident(dict)operator(/)ident(words)
+comment(#-----------------------------)
+
+comment(# @@PLEAC@@_1.8)
+comment(#-----------------------------)
+local_variable($text) operator(=) ident(preg_replace)operator(()delimiter(')string(/)string(\\)string($()string(\\)string(w+\)/e)delimiter(')operator(,) delimiter(')string($$1)delimiter(')operator(,) local_variable($text)operator(\))operator(;)
+comment(#-----------------------------)
+pre_type(list)operator(()local_variable($rows)operator(,) local_variable($cols)operator(\)) operator(=) constant(Array)operator(()integer(24)operator(,) integer(80)operator(\))operator(;)
+local_variable($text) operator(=) delimiter(')string(I am $rows high and $cols long)delimiter(')operator(;)
+local_variable($text) operator(=) ident(preg_replace)operator(()delimiter(')string(/)string(\\)string($()string(\\)string(w+\)/e)delimiter(')operator(,) delimiter(')string($$1)delimiter(')operator(,) local_variable($text)operator(\))operator(;)
+pre_type(print) local_variable($text)operator(;)
+
+comment(#-----------------------------)
+local_variable($text) operator(=) delimiter(")string(I am 17 years old)delimiter(")operator(;)
+local_variable($text) operator(=) ident(preg_replace)operator(()delimiter(')string(/()string(\\)string(d+\)/e)delimiter(')operator(,) delimiter(')string(2*$1)delimiter(')operator(,) local_variable($text)operator(\))operator(;)
+comment(#-----------------------------)
+comment(# expand variables in $text, but put an error message in)
+comment(# if the variable isn't defined)
+local_variable($text) operator(=) ident(preg_replace)operator(()delimiter(')string(/)string(\\)string($()string(\\)string(w+\)/e)delimiter(')operator(,)delimiter(')string(isset($$1\)?$$1:)char(\\')string([NO VARIABLE: $$1])char(\\')delimiter(')operator(,) local_variable($text)operator(\))operator(;)
+comment(#-----------------------------)
+
+comment(// As PHP arrays are used as hashes too, separation of section 4)
+comment(// and section 5 makes little sense.)
+
+comment(# @@PLEAC@@_1.9)
+comment(#-----------------------------)
+local_variable($big) operator(=) ident(strtoupper)operator(()local_variable($little)operator(\))operator(;)
+local_variable($little) operator(=) ident(strtolower)operator(()local_variable($big)operator(\))operator(;)
+comment(// PHP does not have the\\L and\\U string escapes.)
+comment(#-----------------------------)
+local_variable($big) operator(=) ident(ucfirst)operator(()local_variable($little)operator(\))operator(;)
+local_variable($little) operator(=) ident(strtolower)operator(()ident(substr)operator(()local_variable($big)operator(,) integer(0)operator(,) integer(1)operator(\))operator(\)) operator(.) ident(substr)operator(()local_variable($big)operator(,) integer(1)operator(\))operator(;)
+comment(#-----------------------------)
+local_variable($beast) operator(=) delimiter(")string(dromedary)delimiter(")operator(;)
+comment(// capitalize various parts of $beast)
+local_variable($capit) operator(=) ident(ucfirst)operator(()local_variable($beast)operator(\))operator(;) comment(// Dromedar)
+comment(// PHP does not have the\\L and\\U string escapes.)
+local_variable($capall) operator(=) ident(strtoupper)operator(()local_variable($beast)operator(\))operator(;) comment(// DROMEDAR)
+comment(// PHP does not have the\\L and\\U string escapes.)
+local_variable($caprest) operator(=) ident(strtolower)operator(()ident(substr)operator(()local_variable($beast)operator(,) integer(0)operator(,) integer(1)operator(\))operator(\)) operator(.) ident(substr)operator(()ident(strtoupper)operator(()local_variable($beast)operator(\))operator(,) integer(1)operator(\))operator(;) comment(// dROMEDAR)
+comment(// PHP does not have the\\L and\\U string escapes.)
+comment(#-----------------------------)
+comment(// titlecase each word's first character, lowercase the rest)
+local_variable($text) operator(=) delimiter(")string(thIS is a loNG liNE)delimiter(")operator(;)
+local_variable($text) operator(=) ident(ucwords)operator(()ident(strtolower)operator(()local_variable($text)operator(\))operator(\))operator(;)
+pre_type(print) local_variable($text)operator(;)
+constant(This) constant(Is) constant(A) constant(Long) constant(Line)
+comment(#-----------------------------)
+reserved(if) operator(()ident(strtoupper)operator(()local_variable($a)operator(\)) operator(==) ident(strtoupper)operator(()local_variable($b)operator(\))operator(\)) operator({) comment(// or strcasecmp($a, $b\) == 0)
+ pre_type(print) delimiter(")string(a and b are the same)char(\\n)delimiter(")operator(;)
+operator(})
+comment(#-----------------------------)
+comment(# @@INCLUDE@@ include/php/randcap.php)
+
+comment(// % php randcap.php < genesis | head -9)
+comment(#-----------------------------)
+
+comment(# @@PLEAC@@_1.10)
+comment(#-----------------------------)
+pre_type(echo) local_variable($var1) operator(.) ident(func)operator(()operator(\)) operator(.) local_variable($var2)operator(;) comment(// scalar only)
+comment(#-----------------------------)
+comment(// PHP can only handle variable expression without operators)
+local_variable($answer) operator(=) delimiter(")string(STRING )string($)string({)string([ VAR EXPR ]} MORE STRING)delimiter(")operator(;)
+comment(#-----------------------------)
+local_variable($phrase) operator(=) delimiter(")string(I have )delimiter(") operator(.) operator(()local_variable($n) operator(+) integer(1)operator(\)) operator(.) delimiter(")string( guanacos.)delimiter(")operator(;)
+comment(// PHP cannot handle the complex exression: ${\\($n + 1\)})
+comment(#-----------------------------)
+comment(// Rest of Discussion is not applicable to PHP)
+comment(#-----------------------------)
+comment(// Interpolating functions not available in PHP)
+comment(#-----------------------------)
+
+comment(# @@PLEAC@@_1.11)
+comment(# @@INCOMPLETE@@)
+comment(# @@INCOMPLETE@@)
+
+comment(# @@PLEAC@@_1.12)
+comment(#-----------------------------)
+local_variable($output) operator(=) ident(wordwrap)operator(()local_variable($str)operator(,) local_variable($width)operator(,) local_variable($break)operator(,) local_variable($cut)operator(\))operator(;)
+comment(#-----------------------------)
+comment(# @@INCLUDE@@ include/php/wrapdemo.php)
+comment(#-----------------------------)
+comment(// merge multiple lines into one, then wrap one long line)
+pre_type(print) ident(wordwrap)operator(()ident(str_replace)operator(()delimiter(")char(\\n)delimiter(")operator(,) delimiter(")string( )delimiter(")operator(,) ident(file_get_contents)operator(()delimiter(')string(php://stdin)delimiter(')operator(\))operator(\))operator(\))operator(;)
+comment(#-----------------------------)
+reserved(while)operator(()operator(!)ident(feof)operator(()constant(STDIN)operator(\))operator(\)) operator({)
+ pre_type(print) ident(wordwrap)operator(()ident(str_replace)operator(()delimiter(")char(\\n)delimiter(")operator(,) delimiter(")string( )delimiter(")operator(,) ident(stream_get_line)operator(()constant(STDIN)operator(,) integer(0)operator(,) delimiter(")char(\\n)char(\\n)delimiter(")operator(\))operator(\))operator(\))operator(;)
+ pre_type(print) delimiter(")char(\\n)char(\\n)delimiter(")operator(;)
+operator(})
+comment(#-----------------------------)
+
+comment(# @@PLEAC@@_1.13)
+comment(#-----------------------------)
+comment(//backslash)
+local_variable($var) operator(=) ident(preg_replace)operator(()delimiter(')string(/([CHARLIST]\)/)delimiter(')operator(,) delimiter(')char(\\\\)string(\\)string($1)delimiter(')operator(,) local_variable($var)operator(\))operator(;)
+comment(// double)
+local_variable($var) operator(=) ident(preg_replace)operator(()delimiter(')string(/([CHARLIST]\)/)delimiter(')operator(,) delimiter(')string($1$1)delimiter(')operator(,) local_variable($var)operator(\))operator(;)
+comment(#-----------------------------)
+local_variable($var) operator(=) ident(preg_replace)operator(()delimiter(')string(/%/)delimiter(')operator(,) delimiter(')string(%%)delimiter(')operator(,) local_variable($var)operator(\))operator(;)
+comment(#-----------------------------)
+local_variable($string) operator(=) delimiter(')string(Mom said, "Don)char(\\')string(t do that.")delimiter(')operator(;)
+local_variable($string) operator(=) ident(preg_replace)operator(()delimiter(')string(/([)char(\\')string("]\)/)delimiter(')operator(,) delimiter(')char(\\\\)string(\\)string($1)delimiter(')operator(,) local_variable($string)operator(\))operator(;)
+comment(// in PHP you can also use the addslashes(\) function)
+comment(#-----------------------------)
+local_variable($string) operator(=) delimiter(')string(Mom said, "Don)char(\\')string(t do that.")delimiter(')operator(;)
+local_variable($string) operator(=) ident(preg_replace)operator(()delimiter(')string(/([)char(\\')string("]\)/)delimiter(')operator(,) delimiter(')string($1$1)delimiter(')operator(,) local_variable($string)operator(\))operator(;)
+comment(#-----------------------------)
+local_variable($string) operator(=) ident(preg_replace)operator(()delimiter(')string(/([^A-Z]\)/)delimiter(')operator(,) delimiter(')char(\\\\)string(\\)string($1)delimiter(')operator(,) local_variable($string)operator(\))operator(;)
+comment(#-----------------------------)
+comment(// PHP does not have the \\Q and \\E string metacharacters)
+local_variable($string) operator(=) delimiter(")string(this is)char(\\\\)string( a)char(\\\\)string( test)char(\\\\)string(!)delimiter(")operator(;)
+comment(// PHP's quotemeta(\) function is not the same as perl's quotemeta(\) function)
+local_variable($string) operator(=) ident(preg_replace)operator(()delimiter(')string(/()string(\\)string(W\)/)delimiter(')operator(,) delimiter(')char(\\\\)string(\\)string($1)delimiter(')operator(,) delimiter(')string(is a test!)delimiter(')operator(\))operator(;)
+comment(#-----------------------------)
+
+comment(# @@PLEAC@@_1.14)
+comment(#-----------------------------)
+local_variable($string) operator(=) ident(trim)operator(()local_variable($string)operator(\))operator(;)
+comment(#-----------------------------)
+comment(// print what's typed, but surrounded by > < symbols)
+reserved(while) operator(()operator(!)ident(feof)operator(()constant(STDIN)operator(\))operator(\)) operator({)
+ pre_type(print) delimiter(")string(>)delimiter(") operator(.) ident(substr)operator(()ident(fgets)operator(()constant(STDIN)operator(\))operator(,) integer(0)operator(,) integer(-1)operator(\)) operator(.) delimiter(")string(<)char(\\n)delimiter(")operator(;)
+operator(})
+comment(#-----------------------------)
+local_variable($string) operator(=) ident(preg_replace)operator(()delimiter(')string(/)string(\\)string(s+/)delimiter(')operator(,) delimiter(')string( )delimiter(')operator(,) local_variable($string)operator(\))operator(;) comment(// finally, collapse middle)
+comment(#-----------------------------)
+local_variable($string) operator(=) ident(trim)operator(()local_variable($string)operator(\))operator(;)
+local_variable($string) operator(=) ident(preg_replace)operator(()delimiter(')string(/)string(\\)string(s+/)delimiter(')operator(,) delimiter(')string( )delimiter(')operator(,) local_variable($string)operator(\))operator(;)
+comment(#-----------------------------)
+comment(// 1. trim leading and trailing white space)
+comment(// 2. collapse internal whitespace to single space each)
+pre_type(function) ident(sub_trim)operator(()local_variable($string)operator(\)) operator({)
+ local_variable($string) operator(=) ident(trim)operator(()local_variable($string)operator(\))operator(;)
+ local_variable($string) operator(=) ident(preg_replace)operator(()delimiter(')string(/)string(\\)string(s+/)delimiter(')operator(,) delimiter(')string( )delimiter(')operator(,) local_variable($string)operator(\))operator(;)
+ reserved(return) local_variable($string)operator(;)
+operator(})
+comment(#-----------------------------)
+
+comment(# @@PLEAC@@_1.15)
+comment(# @@INCOMPLETE@@)
+comment(# @@INCOMPLETE@@)
+
+comment(# @@PLEAC@@_1.16)
+comment(#-----------------------------)
+local_variable($code) operator(=) ident(soundex)operator(()local_variable($string)operator(\))operator(;)
+comment(#-----------------------------)
+local_variable($phoned_words) operator(=) ident(metaphone)operator(()delimiter(")string(Schwern)delimiter(")operator(\))operator(;)
+comment(#-----------------------------)
+comment(// substitution function for getpwent(\):)
+comment(// returns an array of user entries,)
+comment(// each entry contains the username and the full name)
+pre_type(function) ident(getpwent)operator(()operator(\)) operator({)
+ local_variable($pwents) operator(=) pre_type(array)operator(()operator(\))operator(;)
+ local_variable($handle) operator(=) ident(fopen)operator(()delimiter(")string(passwd)delimiter(")operator(,) delimiter(")string(r)delimiter(")operator(\))operator(;)
+ reserved(while) operator(()operator(!)ident(feof)operator(()local_variable($handle)operator(\))operator(\)) operator({)
+ local_variable($line) operator(=) ident(fgets)operator(()local_variable($handle)operator(\))operator(;)
+ reserved(if) operator(()ident(preg_match)operator(()delimiter(")string(/^#/)delimiter(")operator(,) local_variable($line)operator(\))operator(\)) reserved(continue)operator(;)
+ local_variable($cols) operator(=) ident(explode)operator(()delimiter(")string(:)delimiter(")operator(,) local_variable($line)operator(\))operator(;)
+ local_variable($pwents)operator([)local_variable($cols)operator([)integer(0)operator(])operator(]) operator(=) local_variable($cols)operator([)integer(4)operator(])operator(;)
+ operator(})
+ reserved(return) local_variable($pwents)operator(;)
+operator(})
+
+pre_type(print) delimiter(")string(Lookup user: )delimiter(")operator(;)
+local_variable($user) operator(=) ident(rtrim)operator(()ident(fgets)operator(()constant(STDIN)operator(\))operator(\))operator(;)
+reserved(if) operator(()pre_type(empty)operator(()local_variable($user)operator(\))operator(\)) reserved(exit)operator(;)
+local_variable($name_code) operator(=) ident(soundex)operator(()local_variable($user)operator(\))operator(;)
+local_variable($pwents) operator(=) ident(getpwent)operator(()operator(\))operator(;)
+reserved(foreach)operator(()local_variable($pwents) reserved(as) local_variable($username) operator(=>) local_variable($fullname)operator(\)) operator({)
+ ident(preg_match)operator(()delimiter(")string(/()string(\\)string(w+\)[^,]*)char(\\b)string(()string(\\)string(w+\)/)delimiter(")operator(,) local_variable($fullname)operator(,) local_variable($matches)operator(\))operator(;)
+ pre_type(list)operator(()operator(,) local_variable($firstname)operator(,) local_variable($lastname)operator(\)) operator(=) local_variable($matches)operator(;)
+
+ reserved(if) operator(()local_variable($name_code) operator(==) ident(soundex)operator(()local_variable($username)operator(\)) operator(|)operator(|)
+ local_variable($name_code) operator(==) ident(soundex)operator(()local_variable($lastname)operator(\)) operator(|)operator(|)
+ local_variable($name_code) operator(==) ident(soundex)operator(()local_variable($firstname)operator(\))operator(\))
+ operator({)
+ ident(printf)operator(()delimiter(")string(%s: %s %s)char(\\n)delimiter(")operator(,) local_variable($username)operator(,) local_variable($firstname)operator(,) local_variable($lastname)operator(\))operator(;)
+ operator(})
+operator(})
+comment(#-----------------------------)
+
+comment(# @@PLEAC@@_1.17)
+comment(#-----------------------------)
+comment(# @@INCLUDE@@ include/php/fixstyle.php)
+comment(#-----------------------------)
+comment(# @@INCLUDE@@ include/php/fixstyle2.php)
+comment(#-----------------------------)
+comment(// very fast, but whitespace collapse)
+reserved(while) operator(()operator(!)ident(feof)operator(()local_variable($input)operator(\))operator(\)) operator({)
+ local_variable($i) operator(=) integer(0)operator(;)
+ ident(preg_match)operator(()delimiter(")string(/^()string(\\)string(s*\)(.*\)/)delimiter(")operator(,) ident(fgets)operator(()local_variable($input)operator(\))operator(,) local_variable($matches)operator(\))operator(;) comment(// emit leading whitespace)
+ ident(fwrite)operator(()local_variable($output)operator(,) local_variable($matches)operator([)integer(1)operator(])operator(\))operator(;)
+ reserved(foreach) operator(()ident(preg_split)operator(()delimiter(")string(/()string(\\)string(s+\)/)delimiter(")operator(,) local_variable($matches)operator([)integer(2)operator(])operator(\)) reserved(as) local_variable($token)operator(\)) operator({) comment(// preserve trailing whitespace)
+ ident(fwrite)operator(()local_variable($output)operator(,) operator(()ident(array_key_exists)operator(()local_variable($token)operator(,) local_variable($config)operator(\)) operator(?) local_variable($config)operator([)local_variable($token)operator(]) operator(:) local_variable($token)operator(\)) operator(.) delimiter(")string( )delimiter(")operator(\))operator(;)
+ operator(})
+ ident(fwrite)operator(()local_variable($output)operator(,) delimiter(")char(\\n)delimiter(")operator(\))operator(;)
+operator(})
+comment(#-----------------------------)
+
+comment(// @@PLEAC@@_2.0)
+comment(// As is the case under so many other languages floating point use under PHP is fraught)
+comment(// with dangers. Although the basic techniques shown below are valid, please refer to)
+comment(// the official PHP documentation for known issues, bugs, and alternate approaches )
+
+comment(// @@PLEAC@@_2.1)
+comment(// Two basic approaches to numeric validation:)
+comment(// * Built-in functions like 'is_numeric', 'is_int', 'is_float' etc)
+comment(// * Regexes, as shown below)
+
+local_variable($s) operator(=) delimiter(')string(12.345)delimiter(')operator(;)
+
+ident(preg_match)operator(()delimiter(')string(/)string(\\)string(D/)delimiter(')operator(,) local_variable($s)operator(\)) operator(&)operator(&) reserved(die)operator(()delimiter(")string(has nondigits)char(\\n)delimiter(")operator(\))operator(;)
+ident(preg_match)operator(()delimiter(')string(/^)string(\\)string(d+$/)delimiter(')operator(,) local_variable($s)operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(not a natural number)char(\\n)delimiter(")operator(\))operator(;)
+ident(preg_match)operator(()delimiter(')string(/^-?)string(\\)string(d+$/)delimiter(')operator(,) local_variable($s)operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(not an integer)char(\\n)delimiter(")operator(\))operator(;)
+ident(preg_match)operator(()delimiter(')string(/^[+-]?)string(\\)string(d+$/)delimiter(')operator(,) local_variable($s)operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(not an integer)char(\\n)delimiter(")operator(\))operator(;)
+ident(preg_match)operator(()delimiter(')string(/^-?)string(\\)string(d+)string(\\)string(.?)string(\\)string(d*$/)delimiter(')operator(,) local_variable($s)operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(not a decimal)char(\\n)delimiter(")operator(\))operator(;)
+ident(preg_match)operator(()delimiter(')string(/^-?(?:)string(\\)string(d+(?:)string(\\)string(.)string(\\)string(d*\)?|)string(\\)string(.)string(\\)string(d+\)$/)delimiter(')operator(,) local_variable($s)operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(not a decimal)char(\\n)delimiter(")operator(\))operator(;)
+ident(preg_match)operator(()delimiter(')string(/^([+-]?\)(?=)string(\\)string(d|)string(\\)string(.)string(\\)string(d\))string(\\)string(d*()string(\\)string(.)string(\\)string(d*\)?([Ee]([+-]?)string(\\)string(d+\)\)?$/)delimiter(')operator(,) local_variable($s)operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(not a C float)char(\\n)delimiter(")operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(getnum)operator(()local_variable($s)operator(\))
+operator({)
+ ident(sscanf)operator(()local_variable($s)operator(,) delimiter(")string(%D)delimiter(")operator(,) local_variable($number)operator(\))operator(;) reserved(return) pre_type(isset)operator(()local_variable($number)operator(\)) operator(?) local_variable($number) operator(:) integer(0)operator(;)
+operator(})
+
+pre_type(echo) ident(getnum)operator(()integer(123)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;) comment(// ok)
+pre_type(echo) ident(getnum)operator(()integer(0xf)ident(f)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;) comment(// ..)
+pre_type(echo) ident(getnum)operator(()integer(044)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;) comment(// ..)
+
+pre_type(echo) ident(getnum)operator(()delimiter(')string(x)delimiter(')operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;) comment(// fail)
+
+comment(// @@PLEAC@@_2.2)
+comment(// In PHP floating point comparisions are 'safe' [meaning the '==' comparison operator)
+comment(// can be used] as long as the value consists of 14 digits or less [total digits, either)
+comment(// side of the decimal point e.g. xxxxxxx.xxxxxxx, xxxxxxxxxxxxxx., .xxxxxxxxxxxxxx]. If)
+comment(// values with more digits must be compared, then:)
+comment(//)
+comment(// * Represent as strings, and take care to avoid any implicit conversions e.g. don't pass)
+comment(// a float as a float to a function and expect all digits to be retained - they won't be -)
+comment(// then use 'strcmp' to compare the strings)
+comment(//)
+comment(// * Avoid float use; perhaps use arbitrary precision arithmetic. In this case, the)
+comment(// 'bccomp' function is relevant)
+
+comment(// Will work as long as each floating point value is 14 digits or less)
+reserved(if) operator(()local_variable($float_1) operator(==) local_variable($float_2)operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+comment(// Compare as strings)
+local_variable($cmp) operator(=) ident(strcmp)operator(()delimiter(')string(123456789.123456789123456789)delimiter(')operator(,) delimiter(')string(123456789.123456789123456788)delimiter(')operator(\))operator(;)
+
+comment(// Use 'bccomp')
+local_variable($precision) operator(=) integer(5)operator(;) comment(// Number of significant comparison digits after decimal point)
+reserved(if) operator(()ident(bccomp)operator(()delimiter(')string(1.111117)delimiter(')operator(,) delimiter(')string(1.111116)delimiter(')operator(,) local_variable($precision)operator(\))operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+local_variable($precision) operator(=) integer(6)operator(;)
+reserved(if) operator(()ident(bccomp)operator(()delimiter(')string(1.111117)delimiter(')operator(,) delimiter(')string(1.111116)delimiter(')operator(,) local_variable($precision)operator(\))operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+comment(// ----------------------------)
+
+local_variable($wage) operator(=) integer(536)operator(;)
+local_variable($week) operator(=) local_variable($wage) operator(*) integer(40)operator(;)
+ident(printf)operator(()delimiter(")string(One week's wage is: )string($)string(%.2f)char(\\n)delimiter(")operator(,) local_variable($week) operator(/) integer(100)operator(\))operator(;)
+
+comment(// @@PLEAC@@_2.3)
+comment(// Preferred approach)
+local_variable($rounded) operator(=) ident(round)operator(()local_variable($unrounded)operator(,) local_variable($precision)operator(\))operator(;)
+
+comment(// Possible alternate approach)
+local_variable($format) operator(=) delimiter(')string(%[width].[prec]f)delimiter(')operator(;)
+local_variable($rounded) operator(=) ident(sprintf)operator(()local_variable($format)operator(,) local_variable($unrounded)operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($a) operator(=) integer(0)float(.255)operator(;) local_variable($b) operator(=) ident(round)operator(()local_variable($a)operator(,) integer(2)operator(\))operator(;)
+pre_type(echo) delimiter(")string(Unrounded: )operator({)local_variable($a)operator(})char(\\n)string(Rounded: )operator({)local_variable($b)operator(})char(\\n)delimiter(")operator(;)
+
+local_variable($a) operator(=) integer(0)float(.255)operator(;) local_variable($b) operator(=) ident(sprintf)operator(()delimiter(')string(%.2f)delimiter(')operator(,) local_variable($a)operator(\))operator(;)
+pre_type(echo) delimiter(")string(Unrounded: )operator({)local_variable($a)operator(})char(\\n)string(Rounded: )operator({)local_variable($b)operator(})char(\\n)delimiter(")operator(;)
+
+local_variable($a) operator(=) integer(0)float(.255)operator(;)
+ident(printf)operator(()delimiter(")string(Unrounded: %.f)char(\\n)string(Rounded: %.2f)char(\\n)delimiter(")operator(,) local_variable($a)operator(,) local_variable($a)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(echo) delimiter(")string(number)char(\\t)string(int)char(\\t)string(floor)char(\\t)string(ceil)char(\\n)delimiter(")operator(;)
+
+reserved(foreach)operator(()pre_type(array)operator(()integer(3)float(.3)operator(,) integer(3)float(.5)operator(,) integer(3)float(.7)operator(,) integer(-3)float(.3)operator(\)) reserved(as) local_variable($number)operator(\))
+operator({)
+ ident(printf)operator(()delimiter(")string(%.1f)char(\\t)string(%.1f)char(\\t)string(%.1f)char(\\t)string(%.1f)char(\\n)delimiter(")operator(,) local_variable($number)operator(,) operator(()ident(int)operator(\)) local_variable($number)operator(,) ident(floor)operator(()local_variable($number)operator(\))operator(,) ident(ceil)operator(()local_variable($number)operator(\))operator(\))operator(;)
+operator(})
+
+comment(// @@PLEAC@@_2.4)
+comment(// PHP offers the 'bindec' and 'decbin' functions to converting between binary and decimal)
+
+local_variable($num) operator(=) ident(bindec)operator(()delimiter(')string(0110110)delimiter(')operator(\))operator(;)
+
+local_variable($binstr) operator(=) ident(decbin)operator(()integer(54)operator(\))operator(;)
+
+comment(// @@PLEAC@@_2.5)
+reserved(foreach) operator(()ident(range)operator(()local_variable($X)operator(,) local_variable($Y)operator(\)) reserved(as) local_variable($i)operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+reserved(foreach) operator(()ident(range)operator(()local_variable($X)operator(,) local_variable($Y)operator(,) integer(7)operator(\)) reserved(as) local_variable($i)operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+reserved(for) operator(()local_variable($i) operator(=) local_variable($X)operator(;) local_variable($i) operator(<=) local_variable($Y)operator(;) local_variable($i)operator(++)operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+reserved(for) operator(()local_variable($i) operator(=) local_variable($X)operator(;) local_variable($i) operator(<=) local_variable($Y)operator(;) local_variable($i) operator(+)operator(=) integer(7)operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+comment(// ----------------------------)
+
+pre_type(echo) delimiter(')string(Infancy is:)delimiter(')operator(;) reserved(foreach)operator(()ident(range)operator(()integer(0)operator(,) integer(2)operator(\)) reserved(as) local_variable($i)operator(\)) pre_type(echo) delimiter(")string( )operator({)local_variable($i)operator(})char(\\n)delimiter(")operator(;)
+pre_type(echo) delimiter(')string(Toddling is:)delimiter(')operator(;) reserved(foreach)operator(()ident(range)operator(()integer(3)operator(,) integer(4)operator(\)) reserved(as) local_variable($i)operator(\)) pre_type(echo) delimiter(")string( )operator({)local_variable($i)operator(})char(\\n)delimiter(")operator(;)
+pre_type(echo) delimiter(')string(Childhood is:)delimiter(')operator(;) reserved(foreach)operator(()ident(range)operator(()integer(5)operator(,) integer(12)operator(\)) reserved(as) local_variable($i)operator(\)) pre_type(echo) delimiter(")string( )operator({)local_variable($i)operator(})char(\\n)delimiter(")operator(;)
+
+comment(// @@PLEAC@@_2.6)
+comment(// PHP offers no native support for Roman Numerals. However, a 'Numbers_Roman' class)
+comment(// is available for download from PEAR: [http://pear.php.net/package/Numbers_Roman].)
+comment(// Note the following 'include' directives are required:)
+comment(//)
+comment(// include_once('Numbers/Roman.php'\);)
+
+local_variable($roman) operator(=) constant(Numbers_Roman)operator(::)ident(toNumeral)operator(()local_variable($arabic)operator(\))operator(;)
+local_variable($arabic) operator(=) constant(Numbers_Roman)operator(::)ident(toNumber)operator(()local_variable($roman)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+local_variable($roman_fifteen) operator(=) constant(Numbers_Roman)operator(::)ident(toNumeral)operator(()integer(15)operator(\))operator(;)
+
+local_variable($arabic_fifteen) operator(=) constant(Numbers_Roman)operator(::)ident(toNumber)operator(()local_variable($roman_fifteen)operator(\))operator(;)
+
+ident(printf)operator(()delimiter(")string(Roman for fifteen is: %s)char(\\n)delimiter(")operator(,) local_variable($roman_fifteen)operator(\))operator(;)
+ident(printf)operator(()delimiter(")string(Arabic for fifteen is: %d)char(\\n)delimiter(")operator(,) local_variable($arabic_fifteen)operator(\))operator(;)
+
+comment(// @@PLEAC@@_2.7)
+comment(// Techniques used here simply mirror Perl examples, and are not an endorsement)
+comment(// of any particular RNG technique)
+
+comment(// In PHP do this ...)
+local_variable($random) operator(=) ident(rand)operator(()local_variable($lowerbound)operator(,) local_variable($upperbound)operator(\))operator(;)
+local_variable($random) operator(=) ident(rand)operator(()local_variable($x)operator(,) local_variable($y)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(make_password)operator(()local_variable($chars)operator(,) local_variable($reqlen)operator(\))
+operator({)
+ local_variable($len) operator(=) ident(strlen)operator(()local_variable($chars)operator(\))operator(;)
+ reserved(for) operator(()local_variable($i) operator(=) integer(0)operator(;) local_variable($i) operator(<) local_variable($reqlen)operator(;) local_variable($i)operator(++)operator(\)) local_variable($password) operator(.)operator(=) ident(substr)operator(()local_variable($chars)operator(,) ident(rand)operator(()integer(0)operator(,) local_variable($len)operator(\))operator(,) integer(1)operator(\))operator(;)
+ reserved(return) local_variable($password)operator(;)
+operator(})
+
+local_variable($chars) operator(=) delimiter(')string(ABCDEfghijKLMNOpqrstUVWXYz)delimiter(')operator(;) local_variable($reqlen) operator(=) integer(8)operator(;)
+
+local_variable($password) operator(=) ident(make_password)operator(()local_variable($chars)operator(,) local_variable($reqlen)operator(\))operator(;)
+
+comment(// @@PLEAC@@_2.8)
+comment(// PHP sports a large number of C Standard Library routines including the 'srand')
+comment(// function, used to re-seed the RNG used with calls to the 'rand' function. Thus,)
+comment(// as per Perl example:)
+
+reserved(while) operator(()constant(TRUE)operator(\))
+operator({)
+ local_variable($seed) operator(=) operator(()ident(int)operator(\)) ident(fgets)operator(()constant(STDIN)operator(\))operator(;)
+ reserved(if) operator(()operator(!)pre_type(empty)operator(()local_variable($seed)operator(\))operator(\)) reserved(break)operator(;)
+operator(})
+
+ident(srand)operator(()local_variable($seed)operator(\))operator(;)
+
+comment(// @@PLEAC@@_2.9)
+comment(// The above is considered - for many reasons - a poor way of seeding the RNG. PHP)
+comment(// also offers alternate versions of the functions, 'mt_srand' and 'mt_rand',)
+comment(// which are described as faster, and more 'random', though key to obtaining a)
+comment(// more 'random' distribution of generated numbers seems to be through using)
+comment(// a combination of a previously saved random value in combination with an)
+comment(// unrepeatable value [like the current time in microseconds] that is multiplied)
+comment(// by a large prime number, or perhaps as part of a hash [examples available in)
+comment(// PHP documentation for 'srand' and 'mt_srand'])
+
+ident(mt_srand)operator(()local_variable($saved_random_value) operator(+) ident(microtime)operator(()operator(\)) operator(*) integer(1000003)operator(\))operator(;)
+
+comment(// or)
+
+ident(mt_srand)operator(()operator(()local_variable($saved_random_value) operator(+) ident(hexdec)operator(()ident(substr)operator(()ident(md5)operator(()ident(microtime)operator(()operator(\))operator(\))operator(,) integer(-8)operator(\))operator(\))operator(\)) operator(&) integer(0x7)ident(fffffff)operator(\))operator(;)
+
+comment(// Use of 'mt_rand' together with an appropriate seeding approach should help better)
+comment(// approximate the generation of a 'truly random value')
+local_variable($truly_random_value) operator(=) ident(mt_rand)operator(()operator(\))operator(;)
+
+comment(// @@PLEAC@@_2.10)
+pre_type(function) ident(random)operator(()operator(\)) operator({) reserved(return) operator(()ident(float)operator(\)) ident(rand)operator(()operator(\)) operator(/) operator(()ident(float)operator(\)) ident(getrandmax)operator(()operator(\))operator(;) operator(})
+
+pre_type(function) ident(gaussian_rand)operator(()operator(\))
+operator({)
+ local_variable($u1) operator(=) integer(0)float(.0)operator(;) local_variable($u2) operator(=) integer(0)float(.0)operator(;) local_variable($g1) operator(=) integer(0)float(.0)operator(;) local_variable($g2) operator(=) integer(0)float(.0)operator(;) local_variable($w) operator(=) integer(0)float(.0)operator(;)
+
+ reserved(do)
+ operator({)
+ local_variable($u1) operator(=) integer(2)float(.0) operator(*) ident(random)operator(()operator(\)) operator(-) integer(1)float(.0)operator(;) local_variable($u2) operator(=) integer(2)float(.0) operator(*) ident(random)operator(()operator(\)) operator(-) integer(1)float(.0)operator(;)
+ local_variable($w) operator(=) local_variable($u1) operator(*) local_variable($u1) operator(+) local_variable($u2) operator(*) local_variable($u2)operator(;)
+ operator(}) reserved(while) operator(()local_variable($w) operator(>) integer(1)float(.0)operator(\))operator(;)
+
+ local_variable($w) operator(=) ident(sqrt)operator(()operator(()integer(-2)float(.0) operator(*) ident(log)operator(()local_variable($w)operator(\))operator(\)) operator(/) local_variable($w)operator(\))operator(;) local_variable($g2) operator(=) local_variable($u1) operator(*) local_variable($w)operator(;) local_variable($g1) operator(=) local_variable($u2) operator(*) local_variable($w)operator(;)
+
+ reserved(return) local_variable($g1)operator(;)
+operator(})
+
+comment(// ------------)
+
+local_variable($mean) operator(=) integer(25)float(.0)operator(;) local_variable($sdev) operator(=) integer(2)float(.0)operator(;)
+local_variable($salary) operator(=) ident(gaussian_rand)operator(()operator(\)) operator(*) local_variable($mean) operator(+) local_variable($sdev)operator(;)
+
+ident(printf)operator(()delimiter(")string(You have been hired at: %.2f)char(\\n)delimiter(")operator(,) local_variable($salary)operator(\))operator(;)
+
+comment(// @@PLEAC@@_2.11)
+comment(// 'deg2rad' and 'rad2deg' are actually PHP built-ins, but here is how you might implement)
+operator(/) ident(them) reserved(if) ident(needed)
+pre_type(function) ident(deg2rad_)operator(()local_variable($deg)operator(\)) operator({) reserved(return) operator(()local_variable($deg) operator(/) integer(180)float(.0)operator(\)) operator(*) constant(M_PI)operator(;) operator(})
+pre_type(function) ident(rad2deg_)operator(()local_variable($rad)operator(\)) operator({) reserved(return) operator(()local_variable($rad) operator(/) constant(M_PI)operator(\)) operator(*) integer(180)float(.0)operator(;) operator(})
+
+comment(// ------------)
+
+ident(printf)operator(()delimiter(")string(%f)char(\\n)delimiter(")operator(,) ident(deg2rad_)operator(()integer(180)float(.0)operator(\))operator(\))operator(;)
+ident(printf)operator(()delimiter(")string(%f)char(\\n)delimiter(")operator(,) ident(deg2rad)operator(()integer(180)float(.0)operator(\))operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(degree_sin)operator(()local_variable($deg)operator(\)) operator({) reserved(return) ident(sin)operator(()ident(deg2rad)operator(()local_variable($deg)operator(\))operator(\))operator(;) operator(})
+
+comment(// ------------)
+
+local_variable($rad) operator(=) ident(deg2rad)operator(()integer(380)float(.0)operator(\))operator(;)
+
+ident(printf)operator(()delimiter(")string(%f)char(\\n)delimiter(")operator(,) ident(sin)operator(()local_variable($rad)operator(\))operator(\))operator(;)
+ident(printf)operator(()delimiter(")string(%f)char(\\n)delimiter(")operator(,) ident(degree_sin)operator(()integer(380)float(.0)operator(\))operator(\))operator(;)
+
+comment(// @@PLEAC@@_2.12)
+pre_type(function) ident(my_tan)operator(()local_variable($theta)operator(\)) operator({) reserved(return) ident(sin)operator(()local_variable($theta)operator(\)) operator(/) ident(cos)operator(()local_variable($theta)operator(\))operator(;) operator(})
+
+comment(// ------------)
+
+local_variable($theta) operator(=) integer(3)float(.7)operator(;)
+
+ident(printf)operator(()delimiter(")string(%f)char(\\n)delimiter(")operator(,) ident(my_tan)operator(()local_variable($theta)operator(\))operator(\))operator(;)
+ident(printf)operator(()delimiter(")string(%f)char(\\n)delimiter(")operator(,) ident(tan)operator(()local_variable($theta)operator(\))operator(\))operator(;)
+
+comment(// @@PLEAC@@_2.13)
+local_variable($value) operator(=) integer(100)float(.0)operator(;)
+
+local_variable($log_e) operator(=) ident(log)operator(()local_variable($value)operator(\))operator(;)
+local_variable($log_10) operator(=) ident(log10)operator(()local_variable($value)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(log_base)operator(()local_variable($base)operator(,) local_variable($value)operator(\)) operator({) reserved(return) ident(log)operator(()local_variable($value)operator(\)) operator(/) ident(log)operator(()local_variable($base)operator(\))operator(;) operator(})
+
+comment(// ------------)
+
+local_variable($answer) operator(=) ident(log_base)operator(()integer(10)float(.0)operator(,) integer(10000)float(.0)operator(\))operator(;)
+
+ident(printf)operator(()delimiter(")string(log(10, 10,000\) = %f)char(\\n)delimiter(")operator(,) local_variable($answer)operator(\))operator(;)
+
+comment(// @@PLEAC@@_2.14)
+comment(// PHP offers no native support for matrices. However, a 'Math_Matrix' class)
+comment(// is available for download from PEAR: [http://pear.php.net/package/Math_Matrix].)
+comment(// Note the following 'include' directives are required:)
+comment(//)
+comment(// include_once('Math/Matrix.php'\);)
+
+local_variable($a) operator(=) pre_type(new) constant(Math_Matrix)operator(()pre_type(array)operator(()pre_type(array)operator(()integer(3)operator(,) integer(2)operator(,) integer(3)operator(\))operator(,) pre_type(array)operator(()integer(5)operator(,) integer(9)operator(,) integer(8)operator(\))operator(\))operator(\))operator(;)
+local_variable($b) operator(=) pre_type(new) constant(Math_Matrix)operator(()pre_type(array)operator(()pre_type(array)operator(()integer(4)operator(,) integer(7)operator(\))operator(,) pre_type(array)operator(()integer(9)operator(,) integer(3)operator(\))operator(,) pre_type(array)operator(()integer(8)operator(,) integer(1)operator(\))operator(\))operator(\))operator(;)
+
+pre_type(echo) local_variable($a)operator(->)ident(toString)operator(()operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+pre_type(echo) local_variable($b)operator(->)ident(toString)operator(()operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// NOTE: When I installed this package I had to rename the 'clone' method else)
+comment(// it would not load, so I chose to rename it to 'clone_', and this usage is)
+comment(// shown below. This bug may well be fixed by the time you obtain this package)
+
+local_variable($c) operator(=) local_variable($a)operator(->)ident(clone_)operator(()operator(\))operator(;)
+local_variable($c)operator(->)ident(multiply)operator(()local_variable($b)operator(\))operator(;)
+
+pre_type(echo) local_variable($c)operator(->)ident(toString)operator(()operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// @@PLEAC@@_2.15)
+comment(// PHP offers no native support for complex numbers. However, a 'Math_Complex' class)
+comment(// is available for download from PEAR: [http://pear.php.net/package/Math_Complex].)
+comment(// Note the following 'include' directives are required:)
+comment(//)
+comment(// include_once('Math/Complex.php'\);)
+comment(// include_once('Math/TrigOp.php'\);)
+comment(// include_once('Math/ComplexOp.php'\);)
+
+local_variable($a) operator(=) pre_type(new) constant(Math_Complex)operator(()integer(3)operator(,) integer(5)operator(\))operator(;)
+local_variable($b) operator(=) pre_type(new) constant(Math_Complex)operator(()integer(2)operator(,) integer(-2)operator(\))operator(;)
+
+local_variable($c) operator(=) constant(Math_ComplexOp)operator(::)ident(mult)operator(()local_variable($a)operator(,) local_variable($b)operator(\))operator(;)
+
+pre_type(echo) local_variable($c)operator(->)ident(toString)operator(()operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// ----------------------------)
+
+local_variable($d) operator(=) pre_type(new) constant(Math_Complex)operator(()integer(3)operator(,) integer(4)operator(\))operator(;)
+local_variable($r) operator(=) constant(Math_ComplexOp)operator(::)ident(sqrt)operator(()local_variable($d)operator(\))operator(;)
+
+pre_type(echo) local_variable($r)operator(->)ident(toString)operator(()operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// @@PLEAC@@_2.16)
+comment(// Like C, PHP supports decimal-alternate notations. Thus, for example, the integer)
+comment(// value, 867, is expressable in literal form as:)
+comment(//)
+comment(// Hexadecimal -> 0x363)
+comment(// Octal -> 01543)
+comment(//)
+comment(// For effecting such conversions using strings there is 'sprintf' and 'sscanf'.)
+
+local_variable($dec) operator(=) integer(867)operator(;)
+local_variable($hex) operator(=) ident(sprintf)operator(()delimiter(')string(%x)delimiter(')operator(,) local_variable($dec)operator(\))operator(;)
+local_variable($oct) operator(=) ident(sprintf)operator(()delimiter(')string(%o)delimiter(')operator(,) local_variable($dec)operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($dec) operator(=) integer(0)operator(;)
+local_variable($hex) operator(=) delimiter(')string(363)delimiter(')operator(;)
+
+ident(sscanf)operator(()local_variable($hex)operator(,) delimiter(')string(%x)delimiter(')operator(,) local_variable($dec)operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($dec) operator(=) integer(0)operator(;)
+local_variable($oct) operator(=) delimiter(')string(1543)delimiter(')operator(;)
+
+ident(sscanf)operator(()local_variable($oct)operator(,) delimiter(')string(%o)delimiter(')operator(,) local_variable($dec)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+local_variable($number) operator(=) integer(0)operator(;)
+
+ident(printf)operator(()delimiter(')string(Gimme a number in decimal, octal, or hex: )delimiter(')operator(\))operator(;)
+ident(sscanf)operator(()ident(fgets)operator(()constant(STDIN)operator(\))operator(,) delimiter(')string(%D)delimiter(')operator(,) local_variable($number)operator(\))operator(;)
+
+ident(printf)operator(()delimiter(")string(%d %x %o)char(\\n)delimiter(")operator(,) local_variable($number)operator(,) local_variable($number)operator(,) local_variable($number)operator(\))operator(;)
+
+comment(// @@PLEAC@@_2.17)
+comment(// PHP offers the 'number_format' built-in function to, among many other format tasks, )
+comment(// commify numbers. Perl-compatible [as well as extended] regexes are also available)
+
+pre_type(function) ident(commify_series)operator(()local_variable($s)operator(\)) operator({) reserved(return) ident(number_format)operator(()local_variable($s)operator(,) integer(0)operator(,) delimiter(')delimiter(')operator(,) delimiter(')string(,)delimiter(')operator(\))operator(;) operator(})
+
+comment(// ------------)
+
+local_variable($hits) operator(=) integer(3456789)operator(;)
+
+ident(printf)operator(()delimiter(")string(Your website received %s accesses last month)char(\\n)delimiter(")operator(,) ident(commify_series)operator(()local_variable($hits)operator(\))operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(commify)operator(()local_variable($s)operator(\))
+operator({)
+ reserved(return) ident(strrev)operator(()ident(preg_replace)operator(()delimiter(')string(/()string(\\)string(d)string(\\)string(d)string(\\)string(d\)(?=)string(\\)string(d\)(?!)string(\\)string(d*)string(\\)string(.\)/)delimiter(')operator(,) delimiter(')string(${1},)delimiter(')operator(,) ident(strrev)operator(()local_variable($s)operator(\))operator(\))operator(\))operator(;)
+operator(})
+
+comment(// ------------)
+
+local_variable($hits) operator(=) integer(3456789)operator(;)
+
+pre_type(echo) ident(commify)operator(()ident(sprintf)operator(()delimiter(")string(Your website received %d accesses last month)char(\\n)delimiter(")operator(,) local_variable($hits)operator(\))operator(\))operator(;)
+
+comment(// @@PLEAC@@_2.18)
+pre_type(function) ident(pluralise)operator(()local_variable($value)operator(,) local_variable($root)operator(,) local_variable($singular)operator(=)delimiter(')delimiter(') operator(,) local_variable($plural)operator(=)delimiter(')string(s)delimiter(')operator(\))
+operator({)
+ reserved(return) local_variable($root) operator(.) operator(()operator(()local_variable($value) operator(>) integer(1)operator(\)) operator(?) local_variable($plural) operator(:) local_variable($singular)operator(\))operator(;)
+operator(})
+
+comment(// ------------)
+
+local_variable($duration) operator(=) integer(1)operator(;)
+ident(printf)operator(()delimiter(")string(It took %d %s)char(\\n)delimiter(")operator(,) local_variable($duration)operator(,) ident(pluralise)operator(()local_variable($duration)operator(,) delimiter(')string(hour)delimiter(')operator(\))operator(\))operator(;)
+ident(printf)operator(()delimiter(")string(%d %s %s enough.)char(\\n)delimiter(")operator(,) local_variable($duration)operator(,) ident(pluralise)operator(()local_variable($duration)operator(,) delimiter(')string(hour)delimiter(')operator(\))operator(,)
+ ident(pluralise)operator(()local_variable($duration)operator(,) delimiter(')delimiter(')operator(,) delimiter(')string(is)delimiter(')operator(,) delimiter(')string(are)delimiter(')operator(\))operator(\))operator(;)
+
+local_variable($duration) operator(=) integer(5)operator(;)
+ident(printf)operator(()delimiter(")string(It took %d %s)char(\\n)delimiter(")operator(,) local_variable($duration)operator(,) ident(pluralise)operator(()local_variable($duration)operator(,) delimiter(')string(hour)delimiter(')operator(\))operator(\))operator(;)
+ident(printf)operator(()delimiter(")string(%d %s %s enough.)char(\\n)delimiter(")operator(,) local_variable($duration)operator(,) ident(pluralise)operator(()local_variable($duration)operator(,) delimiter(')string(hour)delimiter(')operator(\))operator(,)
+ ident(pluralise)operator(()local_variable($duration)operator(,) delimiter(')delimiter(')operator(,) delimiter(')string(is)delimiter(')operator(,) delimiter(')string(are)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(plural)operator(()local_variable($singular)operator(\))
+operator({)
+ local_variable($s2p) operator(=) pre_type(array)operator(()delimiter(')string(/ss$/)delimiter(') operator(=>) delimiter(')string(sses)delimiter(')operator(,) delimiter(')string(/([psc]h\)$/)delimiter(') operator(=>) delimiter(')string(${1}es)delimiter(')operator(,) delimiter(')string(/z$/)delimiter(') operator(=>) delimiter(')string(zes)delimiter(')operator(,)
+ delimiter(')string(/ff$/)delimiter(') operator(=>) delimiter(')string(ffs)delimiter(')operator(,) delimiter(')string(/f$/)delimiter(') operator(=>) delimiter(')string(ves)delimiter(')operator(,) delimiter(')string(/ey$/)delimiter(') operator(=>) delimiter(')string(eys)delimiter(')operator(,)
+ delimiter(')string(/y$/)delimiter(') operator(=>) delimiter(')string(ies)delimiter(')operator(,) delimiter(')string(/ix$/)delimiter(') operator(=>) delimiter(')string(ices)delimiter(')operator(,) delimiter(')string(/([sx]\)$/)delimiter(') operator(=>) delimiter(')string($1es)delimiter(')operator(,)
+ delimiter(')string($)delimiter(') operator(=>) delimiter(')string(s)delimiter(')operator(\))operator(;)
+
+ reserved(foreach)operator(()local_variable($s2p) reserved(as) local_variable($s) operator(=>) local_variable($p)operator(\))
+ operator({)
+ reserved(if) operator(()ident(preg_match)operator(()local_variable($s)operator(,) local_variable($singular)operator(\))operator(\)) reserved(return) ident(preg_replace)operator(()local_variable($s)operator(,) local_variable($p)operator(,) local_variable($singular)operator(\))operator(;)
+ operator(})
+operator(})
+
+comment(// ------------)
+
+reserved(foreach)operator(()pre_type(array)operator(()delimiter(')string(mess)delimiter(')operator(,) delimiter(')string(index)delimiter(')operator(,) delimiter(')string(leaf)delimiter(')operator(,) delimiter(')string(puppy)delimiter(')operator(\)) reserved(as) local_variable($word)operator(\))
+operator({)
+ ident(printf)operator(()delimiter(")string(%6s -> %s)char(\\n)delimiter(")operator(,) local_variable($word)operator(,) ident(plural)operator(()local_variable($word)operator(\))operator(\))operator(;)
+operator(})
+
+comment(// @@PLEAC@@_2.19)
+comment(// @@INCOMPLETE@@)
+comment(// @@INCOMPLETE@@)
+
+comment(// @@PLEAC@@_3.0)
+comment(// PHP's date / time suport is quite extensive, and appears grouped into three areas of)
+comment(// functionality:)
+comment(//)
+comment(// * UNIX / C Library [libc]-based routines, which include [among others]:)
+comment(// - localtime, gmtime)
+comment(// - strftime, strptime, mktime)
+comment(// - time, getdate, gettimeofday, )
+comment(//)
+comment(// * PHP 'native' functions, those date / time routines released in earlier versions,)
+comment(// and which otherwise provide 'convenience' functionality; these include:)
+comment(// - date)
+comment(// - strtotime)
+comment(//)
+comment(// * 'DateTime' class-based. This facility appears [according to the PHP documentation])
+comment(// to be extremely new / experimental, so whilst usage examples will be provided, they)
+comment(// should not be taken to be 'official' examples, and obviously, subject to change.)
+comment(// My own impression is that this facility is currently only partially implemented,)
+comment(// so there is limited use for these functions. The functions included in this group)
+comment(// are some of the 'date_'-prefixed functions; they are, however, not used standalone,)
+comment(// but as methods in conjunction with an object. Typical usage:)
+comment(//)
+comment(// $today = new DateTime(\); // actually calls: date_create($today, ...\);)
+comment(// echo $today->format('U'\) . "\\n"; // actually calls: date_format($today, ...\);)
+comment(//)
+comment(// Also worth mentioning is the PEAR [PHP Extension and Repository] package, 'Calendar',)
+comment(// which offers a rich set of date / time manipulation facilities. However, since it is)
+comment(// not currently shipped with PHP, no examples appear)
+
+comment(// Helper functions for performing date arithmetic )
+
+pre_type(function) ident(dateOffset)operator(()operator(\))
+operator({)
+ pre_type(static) local_variable($tbl) operator(=) pre_type(array)operator(()delimiter(')string(sec)delimiter(') operator(=>) integer(1)operator(,) delimiter(')string(min)delimiter(') operator(=>) integer(60)operator(,) delimiter(')string(hou)delimiter(') operator(=>) integer(3600)operator(,) delimiter(')string(day)delimiter(') operator(=>) integer(86400)operator(,) delimiter(')string(wee)delimiter(') operator(=>) integer(604800)operator(\))operator(;)
+ local_variable($delta) operator(=) integer(0)operator(;)
+
+ reserved(foreach) operator(()ident(func_get_args)operator(()operator(\)) reserved(as) local_variable($arg)operator(\))
+ operator({)
+ local_variable($kv) operator(=) ident(explode)operator(()delimiter(')string(=)delimiter(')operator(,) local_variable($arg)operator(\))operator(;)
+ local_variable($delta) operator(+)operator(=) local_variable($kv)operator([)integer(1)operator(]) operator(*) local_variable($tbl)operator([)ident(strtolower)operator(()ident(substr)operator(()local_variable($kv)operator([)integer(0)operator(])operator(,) integer(0)operator(,) integer(3)operator(\))operator(\))operator(])operator(;)
+ operator(})
+
+ reserved(return) local_variable($delta)operator(;)
+operator(})
+
+pre_type(function) ident(dateInterval)operator(()local_variable($intvltype)operator(,) local_variable($timevalue)operator(\))
+operator({)
+ pre_type(static) local_variable($tbl) operator(=) pre_type(array)operator(()delimiter(')string(sec)delimiter(') operator(=>) integer(1)operator(,) delimiter(')string(min)delimiter(') operator(=>) integer(60)operator(,) delimiter(')string(hou)delimiter(') operator(=>) integer(3600)operator(,) delimiter(')string(day)delimiter(') operator(=>) integer(86400)operator(,) delimiter(')string(wee)delimiter(') operator(=>) integer(604800)operator(\))operator(;)
+ reserved(return) operator(()ident(int)operator(\)) ident(round)operator(()local_variable($timevalue) operator(/) local_variable($tbl)operator([)ident(strtolower)operator(()ident(substr)operator(()local_variable($intvltype)operator(,) integer(0)operator(,) integer(3)operator(\))operator(\))operator(])operator(\))operator(;)
+operator(})
+
+comment(// ----------------------------)
+
+comment(// Extract indexed array from 'getdate')
+local_variable($today) operator(=) ident(getdate)operator(()operator(\))operator(;)
+ident(printf)operator(()delimiter(")string(Today is day %d of the current year)char(\\n)delimiter(")operator(,) local_variable($today)operator([)delimiter(')string(yday)delimiter(')operator(])operator(\))operator(;)
+
+comment(// Extract indexed, and associative arrays, respectively, from 'localtime')
+local_variable($today) operator(=) ident(localtime)operator(()operator(\))operator(;)
+ident(printf)operator(()delimiter(")string(Today is day %d of the current year)char(\\n)delimiter(")operator(,) local_variable($today)operator([)integer(7)operator(])operator(\))operator(;)
+
+local_variable($today) operator(=) ident(localtime)operator(()ident(time)operator(()operator(\))operator(,) constant(TRUE)operator(\))operator(;)
+ident(printf)operator(()delimiter(")string(Today is day %d of the current year)char(\\n)delimiter(")operator(,) local_variable($today)operator([)delimiter(')string(tm_yday)delimiter(')operator(])operator(\))operator(;)
+
+comment(// @@PLEAC@@_3.1)
+ident(define)operator(()constant(SEP)operator(,) delimiter(')string(-)delimiter(')operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($today) operator(=) ident(getdate)operator(()operator(\))operator(;)
+
+local_variable($day) operator(=) local_variable($today)operator([)delimiter(')string(mday)delimiter(')operator(])operator(;)
+local_variable($month) operator(=) local_variable($today)operator([)delimiter(')string(mon)delimiter(')operator(])operator(;)
+local_variable($year) operator(=) local_variable($today)operator([)delimiter(')string(year)delimiter(')operator(])operator(;)
+
+comment(// Either do this to use interpolation:)
+local_variable($sep) operator(=) constant(SEP)operator(;)
+pre_type(echo) delimiter(")string(Current date is: )operator({)local_variable($year)operator(})operator({)local_variable($sep)operator(})operator({)local_variable($month)operator(})operator({)local_variable($sep)operator(})operator({)local_variable($day)operator(})char(\\n)delimiter(")operator(;)
+
+comment(// or simply concatenate:)
+pre_type(echo) delimiter(')string(Current date is: )delimiter(') operator(.) local_variable($year) operator(.) constant(SEP) operator(.) local_variable($month) operator(.) constant(SEP) operator(.) local_variable($day) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// ------------)
+
+local_variable($today) operator(=) ident(localtime)operator(()ident(time)operator(()operator(\))operator(,) constant(TRUE)operator(\))operator(;)
+
+local_variable($day) operator(=) local_variable($today)operator([)delimiter(')string(tm_mday)delimiter(')operator(])operator(;)
+local_variable($month) operator(=) local_variable($today)operator([)delimiter(')string(tm_mon)delimiter(')operator(]) operator(+) integer(1)operator(;)
+local_variable($year) operator(=) local_variable($today)operator([)delimiter(')string(tm_year)delimiter(')operator(]) operator(+) integer(1900)operator(;)
+
+ident(printf)operator(()delimiter(")string(Current date is: %4d%s%2d%s%2d)char(\\n)delimiter(")operator(,) local_variable($year)operator(,) constant(SEP)operator(,) local_variable($month)operator(,) constant(SEP)operator(,) local_variable($day)operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($format) operator(=) delimiter(')string(Y)delimiter(') operator(.) constant(SEP) operator(.) delimiter(')string(n)delimiter(') operator(.) constant(SEP) operator(.) delimiter(')string(d)delimiter(')operator(;)
+
+local_variable($today) operator(=) ident(date)operator(()local_variable($format)operator(\))operator(;)
+
+pre_type(echo) delimiter(")string(Current date is: )operator({)local_variable($today)operator(})char(\\n)delimiter(")operator(;)
+
+comment(// ------------)
+
+local_variable($sep) operator(=) constant(SEP)operator(;)
+
+local_variable($today) operator(=) ident(strftime)operator(()delimiter(")string(%Y)local_variable($sep)string(%m)local_variable($sep)string(%d)delimiter(")operator(\))operator(;)
+
+pre_type(echo) delimiter(")string(Current date is: )operator({)local_variable($today)operator(})char(\\n)delimiter(")operator(;)
+
+comment(// @@PLEAC@@_3.2)
+local_variable($timestamp) operator(=) ident(mktime)operator(()local_variable($hour)operator(,) local_variable($min)operator(,) local_variable($sec)operator(,) local_variable($month)operator(,) local_variable($day)operator(,) local_variable($year)operator(\))operator(;)
+
+local_variable($timestamp) operator(=) ident(gmmktime)operator(()local_variable($hour)operator(,) local_variable($min)operator(,) local_variable($sec)operator(,) local_variable($month)operator(,) local_variable($day)operator(,) local_variable($year)operator(\))operator(;)
+
+comment(// @@PLEAC@@_3.3)
+local_variable($dmyhms) operator(=) ident(getdate)operator(()operator(\))operator(;) comment(// timestamp: current date / time)
+
+local_variable($dmyhms) operator(=) ident(getdate)operator(()local_variable($timestamp)operator(\))operator(;) comment(// timestamp: arbitrary)
+
+local_variable($day) operator(=) local_variable($dmyhms)operator([)delimiter(')string(mday)delimiter(')operator(])operator(;)
+local_variable($month) operator(=) local_variable($dmyhms)operator([)delimiter(')string(mon)delimiter(')operator(])operator(;)
+local_variable($year) operator(=) local_variable($dmyhms)operator([)delimiter(')string(year)delimiter(')operator(])operator(;)
+
+local_variable($hours) operator(=) local_variable($dmyhms)operator([)delimiter(')string(hours)delimiter(')operator(])operator(;)
+local_variable($minutes) operator(=) local_variable($dmyhms)operator([)delimiter(')string(minutes)delimiter(')operator(])operator(;)
+local_variable($seconds) operator(=) local_variable($dmyhms)operator([)delimiter(')string(seconds)delimiter(')operator(])operator(;)
+
+comment(// @@PLEAC@@_3.4)
+comment(// Date arithmetic is probably most easily performed using timestamps [i.e. *NIX Epoch)
+comment(// Seconds]. Dates - in whatever form - are converted to timestamps, these are)
+comment(// arithmetically manipulated, and the result converted to whatever form required.)
+comment(// Note: use 'mktime' to create timestamps properly adjusted for daylight saving; whilst)
+comment(// 'strtotime' is more convenient to use, it does not, AFAIK, include this adjustment)
+
+local_variable($when) operator(=) local_variable($now) operator(+) local_variable($difference)operator(;)
+local_variable($then) operator(=) local_variable($now) operator(-) local_variable($difference)operator(;)
+
+comment(// ------------)
+
+local_variable($now) operator(=) ident(mktime)operator(()integer(0)operator(,) integer(0)operator(,) integer(0)operator(,) integer(8)operator(,) integer(6)operator(,) integer(2003)operator(\))operator(;)
+
+local_variable($diff1) operator(=) ident(dateOffset)operator(()delimiter(')string(day=1)delimiter(')operator(\))operator(;) local_variable($diff2) operator(=) ident(dateOffset)operator(()delimiter(')string(weeks=2)delimiter(')operator(\))operator(;)
+
+pre_type(echo) delimiter(')string(Today is: )delimiter(') operator(.) ident(date)operator(()delimiter(')string(Y-m-d)delimiter(')operator(,) local_variable($now)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+pre_type(echo) delimiter(')string(One day in the future is: )delimiter(') operator(.) ident(date)operator(()delimiter(')string(Y-m-d)delimiter(')operator(,) local_variable($now) operator(+) local_variable($diff1)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+pre_type(echo) delimiter(')string(Two weeks in the past is: )delimiter(') operator(.) ident(date)operator(()delimiter(')string(Y-m-d)delimiter(')operator(,) local_variable($now) operator(-) local_variable($diff2)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// ----------------------------)
+
+comment(// Date arithmetic performed using a custom function, 'dateOffset'. Internally, offset may)
+comment(// be computed in one of several ways:)
+comment(// * Direct timestamp manipulation - fastest, but no daylight saving adjustment )
+comment(// * Via 'date' built-in function - slower [?], needs a base time from which to)
+comment(// compute values, but has daylight saving adjustment )
+comment(// * Via 'strtotime' built-in function - as for 'date')
+comment(// * Via 'DateTime' class)
+comment(//)
+comment(// Approach used here is to utilise direct timestamp manipulation in 'dateOffset' [it's)
+comment(// performance can also be improved by replacing $tbl with a global definition etc],)
+comment(// and to illustrate how the other approaches might be used )
+
+comment(// 1. 'dateOffset')
+
+local_variable($birthtime) operator(=) ident(mktime)operator(()integer(3)operator(,) integer(45)operator(,) integer(50)operator(,) integer(1)operator(,) integer(18)operator(,) integer(1973)operator(\))operator(;)
+
+local_variable($interval) operator(=) ident(dateOffset)operator(()delimiter(')string(day=55)delimiter(')operator(,) delimiter(')string(hours=2)delimiter(')operator(,) delimiter(')string(min=17)delimiter(')operator(,) delimiter(')string(sec=5)delimiter(')operator(\))operator(;)
+
+local_variable($then) operator(=) local_variable($birthtime) operator(+) local_variable($interval)operator(;)
+
+ident(printf)operator(()delimiter(")string(Birthtime is: %s)char(\\n)string(then is: %s)char(\\n)delimiter(")operator(,) ident(date)operator(()constant(DATE_RFC1123)operator(,) local_variable($birthtime)operator(\))operator(,) ident(date)operator(()constant(DATE_RFC1123)operator(,) local_variable($then)operator(\))operator(\))operator(;)
+
+comment(// ------------)
+
+comment(// 2. 'date')
+
+comment(// Base values, and offsets, respectively)
+local_variable($hr) operator(=) integer(3)operator(;) local_variable($min) operator(=) integer(45)operator(;) local_variable($sec) operator(=) integer(50)operator(;) local_variable($mon) operator(=) integer(1)operator(;) local_variable($day) operator(=) integer(18)operator(;) local_variable($year) operator(=) integer(1973)operator(;)
+
+local_variable($yroff) operator(=) integer(0)operator(;) local_variable($monoff) operator(=) integer(0)operator(;) local_variable($dayoff) operator(=) integer(55)operator(;) local_variable($hroff) operator(=) integer(2)operator(;) local_variable($minoff) operator(=) integer(17)operator(;) local_variable($secoff) operator(=) integer(5)operator(;)
+
+comment(// Base date)
+local_variable($birthtime) operator(=) ident(mktime)operator(()local_variable($hr)operator(,) local_variable($min)operator(,) local_variable($sec)operator(,) local_variable($mon)operator(,) local_variable($day)operator(,) local_variable($year)operator(,) constant(TRUE)operator(\))operator(;)
+
+local_variable($year) operator(=) ident(date)operator(()delimiter(')string(Y)delimiter(')operator(,) local_variable($birthtime)operator(\)) operator(+) local_variable($yroff)operator(;)
+local_variable($mon) operator(=) ident(date)operator(()delimiter(')string(m)delimiter(')operator(,) local_variable($birthtime)operator(\)) operator(+) local_variable($monoff)operator(;)
+local_variable($day) operator(=) ident(date)operator(()delimiter(')string(d)delimiter(')operator(,) local_variable($birthtime)operator(\)) operator(+) local_variable($dayoff)operator(;)
+
+local_variable($hr) operator(=) ident(date)operator(()delimiter(')string(H)delimiter(')operator(,) local_variable($birthtime)operator(\)) operator(+) local_variable($hroff)operator(;)
+local_variable($min) operator(=) ident(date)operator(()delimiter(')string(i)delimiter(')operator(,) local_variable($birthtime)operator(\)) operator(+) local_variable($minoff)operator(;)
+local_variable($sec) operator(=) ident(date)operator(()delimiter(')string(s)delimiter(')operator(,) local_variable($birthtime)operator(\)) operator(+) local_variable($secoff)operator(;)
+
+comment(// Offset date)
+local_variable($then) operator(=) ident(mktime)operator(()local_variable($hr)operator(,) local_variable($min)operator(,) local_variable($sec)operator(,) local_variable($mon)operator(,) local_variable($day)operator(,) local_variable($year)operator(,) constant(TRUE)operator(\))operator(;)
+
+ident(printf)operator(()delimiter(")string(Birthtime is: %s)char(\\n)string(then is: %s)char(\\n)delimiter(")operator(,) ident(date)operator(()constant(DATE_RFC1123)operator(,) local_variable($birthtime)operator(\))operator(,) ident(date)operator(()constant(DATE_RFC1123)operator(,) local_variable($then)operator(\))operator(\))operator(;)
+
+comment(// ------------)
+
+comment(// 3. 'strtotime')
+
+comment(// Generate timestamp whatever way is preferable)
+local_variable($birthtime) operator(=) ident(mktime)operator(()integer(3)operator(,) integer(45)operator(,) integer(50)operator(,) integer(1)operator(,) integer(18)operator(,) integer(1973)operator(\))operator(;)
+local_variable($birthtime) operator(=) ident(strtotime)operator(()delimiter(')string(1/18/1973 03:45:50)delimiter(')operator(\))operator(;)
+
+local_variable($then) operator(=) ident(strtotime)operator(()delimiter(')string(+55 days 2 hours 17 minutes 2 seconds)delimiter(')operator(,) local_variable($birthtime)operator(\))operator(;)
+
+ident(printf)operator(()delimiter(")string(Birthtime is: %s)char(\\n)string(then is: %s)char(\\n)delimiter(")operator(,) ident(date)operator(()constant(DATE_RFC1123)operator(,) local_variable($birthtime)operator(\))operator(,) ident(date)operator(()constant(DATE_RFC1123)operator(,) local_variable($then)operator(\))operator(\))operator(;)
+
+comment(// ------------)
+
+comment(// 4. 'DateTime' class)
+
+local_variable($birthtime) operator(=) pre_type(new) constant(DateTime)operator(()delimiter(')string(1/18/1973 03:45:50)delimiter(')operator(\))operator(;)
+local_variable($then) operator(=) pre_type(new) constant(DateTime)operator(()delimiter(')string(1/18/1973 03:45:50)delimiter(')operator(\))operator(;)
+local_variable($then)operator(->)ident(modify)operator(()delimiter(')string(+55 days 2 hours 17 minutes 2 seconds)delimiter(')operator(\))operator(;)
+
+ident(printf)operator(()delimiter(")string(Birthtime is: %s)char(\\n)string(then is: %s)char(\\n)delimiter(")operator(,) local_variable($birthtime)operator(->)ident(format)operator(()constant(DATE_RFC1123)operator(\))operator(,) local_variable($then)operator(->)ident(format)operator(()constant(DATE_RFC1123)operator(\))operator(\))operator(;)
+
+comment(// @@PLEAC@@_3.5)
+comment(// Date intervals are most easily computed using timestamps [i.e. *NIX Epoch)
+comment(// Seconds] which, of course, gives the interval result is seconds from which)
+comment(// all other interval measures [days, weeks, months, years] may be derived.)
+comment(// Refer to previous section for discussion of daylight saving and other related)
+comment(// problems)
+
+local_variable($interval_seconds) operator(=) local_variable($recent) operator(-) local_variable($earlier)operator(;)
+
+comment(// ----------------------------)
+
+comment(// Conventional approach ...)
+local_variable($bree) operator(=) ident(strtotime)operator(()delimiter(')string(16 Jun 1981, 4:35:25)delimiter(')operator(\))operator(;)
+local_variable($nat) operator(=) ident(strtotime)operator(()delimiter(')string(18 Jan 1973, 3:45:50)delimiter(')operator(\))operator(;)
+
+comment(// ... or, with daylight saving adjustment)
+local_variable($bree) operator(=) ident(mktime)operator(()integer(4)operator(,) integer(35)operator(,) integer(25)operator(,) integer(6)operator(,) integer(16)operator(,) integer(1981)operator(,) constant(TRUE)operator(\))operator(;)
+local_variable($nat) operator(=) ident(mktime)operator(()integer(3)operator(,) integer(45)operator(,) integer(50)operator(,) integer(1)operator(,) integer(18)operator(,) integer(1973)operator(,) constant(TRUE)operator(\))operator(;)
+
+local_variable($difference) operator(=) local_variable($bree) operator(-) local_variable($nat)operator(;)
+
+comment(// 'dateInterval' custom function computes intervals in several measures given an)
+comment(// interval in seconds. Note, 'month' and 'year' measures not provided)
+ident(printf)operator(()delimiter(")string(There were %d seconds between Nat and Bree)char(\\n)delimiter(")operator(,) local_variable($difference)operator(\))operator(;)
+ident(printf)operator(()delimiter(")string(There were %d weeks between Nat and Bree)char(\\n)delimiter(")operator(,) ident(dateInterval)operator(()delimiter(')string(weeks)delimiter(')operator(,) local_variable($difference)operator(\))operator(\))operator(;)
+ident(printf)operator(()delimiter(")string(There were %d days between Nat and Bree)char(\\n)delimiter(")operator(,) ident(dateInterval)operator(()delimiter(')string(days)delimiter(')operator(,) local_variable($difference)operator(\))operator(\))operator(;)
+ident(printf)operator(()delimiter(")string(There were %d hours between Nat and Bree)char(\\n)delimiter(")operator(,) ident(dateInterval)operator(()delimiter(')string(hours)delimiter(')operator(,) local_variable($difference)operator(\))operator(\))operator(;)
+ident(printf)operator(()delimiter(")string(There were %d minutes between Nat and Bree)char(\\n)delimiter(")operator(,) ident(dateInterval)operator(()delimiter(')string(mins)delimiter(')operator(,) local_variable($difference)operator(\))operator(\))operator(;)
+
+comment(// @@PLEAC@@_3.6)
+comment(// 'getdate' accepts a timestamp [or implicitly calls 'time'] and returns an array of)
+comment(// date components. It returns much the same information as 'strptime' except that)
+comment(// the component names are different)
+
+local_variable($today) operator(=) ident(getdate)operator(()operator(\))operator(;)
+
+local_variable($weekday) operator(=) local_variable($today)operator([)delimiter(')string(wday)delimiter(')operator(])operator(;)
+local_variable($monthday) operator(=) local_variable($today)operator([)delimiter(')string(mday)delimiter(')operator(])operator(;)
+local_variable($yearday) operator(=) local_variable($today)operator([)delimiter(')string(yday)delimiter(')operator(])operator(;)
+
+local_variable($weeknumber) operator(=) operator(()ident(int)operator(\)) ident(round)operator(()local_variable($yearday) operator(/) integer(7)float(.0)operator(\))operator(;)
+
+comment(// Safter method of obtaining week number)
+local_variable($weeknumber) operator(=) ident(strftime)operator(()delimiter(')string(%U)delimiter(')operator(\)) operator(+) integer(1)operator(;)
+
+comment(// ----------------------------)
+
+ident(define)operator(()constant(SEP)operator(,) delimiter(')string(/)delimiter(')operator(\))operator(;)
+
+local_variable($day) operator(=) integer(16)operator(;)
+local_variable($month) operator(=) integer(6)operator(;)
+local_variable($year) operator(=) integer(1981)operator(;)
+
+local_variable($timestamp) operator(=) ident(mktime)operator(()integer(0)operator(,) integer(0)operator(,) integer(0)operator(,) local_variable($month)operator(,) local_variable($day)operator(,) local_variable($year)operator(\))operator(;)
+
+local_variable($date) operator(=) ident(getdate)operator(()local_variable($timestamp)operator(\))operator(;)
+
+local_variable($weekday) operator(=) local_variable($date)operator([)delimiter(')string(wday)delimiter(')operator(])operator(;)
+local_variable($monthday) operator(=) local_variable($date)operator([)delimiter(')string(mday)delimiter(')operator(])operator(;)
+local_variable($yearday) operator(=) local_variable($date)operator([)delimiter(')string(yday)delimiter(')operator(])operator(;)
+
+local_variable($weeknumber) operator(=) operator(()ident(int)operator(\)) ident(round)operator(()local_variable($yearday) operator(/) integer(7)float(.0)operator(\))operator(;)
+
+local_variable($weeknumber) operator(=) ident(strftime)operator(()delimiter(')string(%U)delimiter(')operator(,) local_variable($timestamp)operator(\)) operator(+) integer(1)operator(;)
+
+comment(// Interpolate ...)
+local_variable($sep) operator(=) constant(SEP)operator(;)
+pre_type(echo) delimiter(")operator({)local_variable($month)operator(})operator({)local_variable($sep)operator(})operator({)local_variable($day)operator(})operator({)local_variable($sep)operator(})operator({)local_variable($year)operator(})string( was a )operator({)local_variable($date)operator([)delimiter(')string(weekday)delimiter(')operator(])operator(})string( in week )operator({)local_variable($weeknumber)operator(})char(\\n)delimiter(")operator(;)
+
+comment(// ... or, concatenate)
+pre_type(echo) local_variable($month) operator(.) constant(SEP) operator(.) local_variable($day) operator(.) constant(SEP) operator(.) local_variable($year) operator(.) delimiter(')string( was a )delimiter(') operator(.) local_variable($date)operator([)delimiter(')string(weekday)delimiter(')operator(])
+ operator(.) delimiter(')string( in week )delimiter(') operator(.) local_variable($weeknumber) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// @@PLEAC@@_3.7)
+comment(// 'strtotime' parses a textual date expression by attempting a 'best guess' at)
+comment(// the format, and either fails, or generates a timestamp. Timestamp could be fed)
+comment(// into any one of the various functions; example:)
+local_variable($timestamp) operator(=) ident(strtotime)operator(()delimiter(')string(1998-06-03)delimiter(')operator(\))operator(;) pre_type(echo) ident(strftime)operator(()delimiter(')string(%Y-%m-%d)delimiter(')operator(,) local_variable($timestamp)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// 'strptime' parses a textual date expression according to a specified format,)
+comment(// and returns an array of date components; components can be easily dumped)
+ident(print_r)operator(()ident(strptime)operator(()delimiter(')string(1998-06-03)delimiter(')operator(,) delimiter(')string(%Y-%m-%d)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// ----------------------------)
+
+comment(// Parse date string according to format)
+local_variable($darr) operator(=) ident(strptime)operator(()delimiter(')string(1998-06-03)delimiter(')operator(,) delimiter(')string(%Y-%m-%d)delimiter(')operator(\))operator(;)
+
+reserved(if) operator(()operator(!)pre_type(empty)operator(()local_variable($darr)operator(\))operator(\))
+operator({)
+ comment(// Show date components in 'debug' form)
+ ident(print_r)operator(()local_variable($darr)operator(\))operator(;)
+
+ comment(// Check whether there was a parse error i.e. one or more components could not)
+ comment(// be extracted from the string)
+ reserved(if) operator(()pre_type(empty)operator(()local_variable($darr)operator([)delimiter(')string(unparsed)delimiter(')operator(])operator(\))operator(\))
+ operator({)
+ comment(// Properly parsed date, so validate required components using, 'checkdate')
+ reserved(if) operator(()ident(checkdate)operator(()local_variable($darr)operator([)delimiter(')string(tm_mon)delimiter(')operator(]) operator(+) integer(1)operator(,) local_variable($darr)operator([)delimiter(')string(tm_mday)delimiter(')operator(])operator(,) local_variable($darr)operator([)delimiter(')string(tm_year)delimiter(')operator(]) operator(+) integer(1900)operator(\))operator(\))
+ pre_type(echo) delimiter(")string(Parsed date verified as correct)char(\\n)delimiter(")operator(;)
+ reserved(else)
+ pre_type(echo) delimiter(")string(Parsed date failed verification)char(\\n)delimiter(")operator(;)
+ operator(})
+ reserved(else)
+ operator({)
+ pre_type(echo) delimiter(")string(Date string parse not complete; failed components: )operator({)local_variable($darr)operator([)delimiter(')string(unparsed)delimiter(')operator(])operator(})char(\\n)delimiter(")operator(;)
+ operator(})
+operator(})
+reserved(else)
+operator({)
+ pre_type(echo) delimiter(")string(Date string could not be parsed)char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// @@PLEAC@@_3.8)
+comment(// 'date' and 'strftime' both print a date string based on:)
+comment(// * Format String, describing layout of date components)
+comment(// * Timestamp [*NIX Epoch Seconds], either given explicitly, or implictly)
+comment(// via a call to 'time' which retrieves current time value)
+
+local_variable($ts) operator(=) integer(1234567890)operator(;)
+
+ident(date)operator(()delimiter(')string(Y/m/d)delimiter(')operator(,) local_variable($ts)operator(\))operator(;)
+ident(date)operator(()delimiter(')string(Y/m/d)delimiter(')operator(,) ident(mktime)operator(()local_variable($h)operator(,) local_variable($m)operator(,) local_variable($s)operator(,) local_variable($mth)operator(,) local_variable($d)operator(,) local_variable($y)operator(,) local_variable($is_dst)operator(\))operator(\))operator(;)
+
+ident(date)operator(()delimiter(')string(Y/m/d)delimiter(')operator(\))operator(;) comment(// same as: date('Y/m/d', time(\)\);)
+
+comment(// ------------)
+
+local_variable($ts) operator(=) integer(1234567890)operator(;)
+
+ident(strftime)operator(()delimiter(')string(%Y/%m/%d)delimiter(')operator(,) local_variable($ts)operator(\))operator(;)
+ident(strftime)operator(()delimiter(')string(%Y/%m/%d)delimiter(')operator(,) ident(mktime)operator(()local_variable($h)operator(,) local_variable($m)operator(,) local_variable($s)operator(,) local_variable($mth)operator(,) local_variable($d)operator(,) local_variable($y)operator(,) local_variable($is_dst)operator(\))operator(\))operator(;)
+
+ident(strftime)operator(()delimiter(')string(%Y/%m/%d)delimiter(')operator(\))operator(;) comment(// same as: strftime('%Y/%m/%d', time(\)\);)
+
+comment(// ----------------------------)
+
+comment(// 'mktime' creates a local time timestamp)
+local_variable($t) operator(=) ident(strftime)operator(()delimiter(')string(%a %b %e %H:%M:%S %z %Y)delimiter(')operator(,) ident(mktime)operator(()integer(3)operator(,) integer(45)operator(,) integer(50)operator(,) integer(1)operator(,) integer(18)operator(,) integer(73)operator(,) constant(TRUE)operator(\))operator(\))operator(;)
+pre_type(echo) delimiter(")operator({)local_variable($t)operator(})char(\\n)delimiter(")operator(;)
+
+comment(// 'gmmktime' creates a GMT time timestamp)
+local_variable($t) operator(=) ident(strftime)operator(()delimiter(')string(%a %b %e %H:%M:%S %z %Y)delimiter(')operator(,) ident(gmmktime)operator(()integer(3)operator(,) integer(45)operator(,) integer(50)operator(,) integer(1)operator(,) integer(18)operator(,) integer(73)operator(\))operator(\))operator(;)
+pre_type(echo) delimiter(")operator({)local_variable($t)operator(})char(\\n)delimiter(")operator(;)
+
+comment(// ----------------------------)
+
+comment(// 'strtotime' parses a textual date expression, and generates a timestamp )
+local_variable($t) operator(=) ident(strftime)operator(()delimiter(')string(%A %D)delimiter(')operator(,) ident(strtotime)operator(()delimiter(')string(18 Jan 1973, 3:45:50)delimiter(')operator(\))operator(\))operator(;)
+pre_type(echo) delimiter(")operator({)local_variable($t)operator(})char(\\n)delimiter(")operator(;)
+
+comment(// This should generate output identical to previous example)
+local_variable($t) operator(=) ident(strftime)operator(()delimiter(')string(%A %D)delimiter(')operator(,) ident(mktime)operator(()integer(3)operator(,) integer(45)operator(,) integer(50)operator(,) integer(1)operator(,) integer(18)operator(,) integer(73)operator(,) constant(TRUE)operator(\))operator(\))operator(;)
+pre_type(echo) delimiter(")operator({)local_variable($t)operator(})char(\\n)delimiter(")operator(;)
+
+comment(// @@PLEAC@@_3.9)
+comment(// PHP 5 and above can use the built-in, 'microtime'. Crude implementation for ealier versions:)
+comment(// function microtime(\) { $t = gettimeofday(\); return (float\) ($t['sec'] + $t['usec'] / 1000000.0\); } )
+
+comment(// ------------)
+
+local_variable($before) operator(=) ident(microtime)operator(()operator(\))operator(;)
+
+local_variable($line) operator(=) ident(fgets)operator(()constant(STDIN)operator(\))operator(;)
+
+local_variable($elapsed) operator(=) ident(microtime)operator(()operator(\)) operator(-) local_variable($before)operator(;)
+
+ident(printf)operator(()delimiter(")string(You took %.3f seconds)char(\\n)delimiter(")operator(,) local_variable($elapsed)operator(\))operator(;)
+
+comment(// ------------)
+
+ident(define)operator(()constant(NUMBER_OF_TIMES)operator(,) integer(100)operator(\))operator(;)
+ident(define)operator(()constant(SIZE)operator(,) integer(500)operator(\))operator(;)
+
+reserved(for)operator(()local_variable($i) operator(=) integer(0)operator(;) local_variable($i) operator(<) constant(NUMBER_OF_TIMES)operator(;) local_variable($i)operator(++)operator(\))
+operator({)
+ local_variable($arr) operator(=) pre_type(array)operator(()operator(\))operator(;)
+ reserved(for)operator(()local_variable($j) operator(=) integer(0)operator(;) local_variable($j) operator(<) constant(SIZE)operator(;) local_variable($j)operator(++)operator(\)) local_variable($arr)operator([)operator(]) operator(=) ident(rand)operator(()operator(\))operator(;)
+
+ local_variable($begin) operator(=) ident(microtime)operator(()operator(\))operator(;)
+ ident(sort)operator(()local_variable($arr)operator(\))operator(;)
+ local_variable($elapsed) operator(=) ident(microtime)operator(()operator(\)) operator(-) local_variable($begin)operator(;)
+
+ local_variable($total_time) operator(+)operator(=) local_variable($elapsed)operator(;)
+operator(})
+
+ident(printf)operator(()delimiter(")string(On average, sorting %d random numbers takes %.5f seconds)char(\\n)delimiter(")operator(,) constant(SIZE)operator(,) local_variable($total_time) operator(/) operator(()ident(float)operator(\)) constant(NUMBER_OF_TIMES)operator(\))operator(;)
+
+comment(// @@PLEAC@@_3.10)
+comment(// Low-resolution: sleep time specified in seconds)
+ident(sleep)operator(()integer(1)operator(\))operator(;)
+
+comment(// High-resolution: sleep time specified in microseconds [not reliable under Windows])
+ident(usleep)operator(()integer(250000)operator(\))operator(;)
+
+comment(// @@PLEAC@@_3.11)
+comment(// @@INCOMPLETE@@)
+comment(// @@INCOMPLETE@@)
+
+comment(// @@PLEAC@@_4.0)
+comment(// Nested arrays are supported, and may be easily printed using 'print_r')
+
+local_variable($nested) operator(=) pre_type(array)operator(()delimiter(')string(this)delimiter(')operator(,) delimiter(')string(that)delimiter(')operator(,) delimiter(')string(the)delimiter(')operator(,) delimiter(')string(other)delimiter(')operator(\))operator(;)
+
+local_variable($nested) operator(=) pre_type(array)operator(()delimiter(')string(this)delimiter(')operator(,) delimiter(')string(that)delimiter(')operator(,) pre_type(array)operator(()delimiter(')string(the)delimiter(')operator(,) delimiter(')string(other)delimiter(')operator(\))operator(\))operator(;) ident(print_r)operator(()local_variable($nested)operator(\))operator(;)
+
+local_variable($tune) operator(=) pre_type(array)operator(()delimiter(')string(The)delimiter(')operator(,) delimiter(')string(Star-Spangled)delimiter(')operator(,) delimiter(')string(Banner)delimiter(')operator(\))operator(;)
+
+comment(// @@PLEAC@@_4.1)
+comment(// PHP offers only the 'array' type which is actually an associative array, though)
+comment(// may be numerically indexed, to mimic vectors and matrices; there is no separate)
+comment(// 'list' type)
+
+local_variable($a) operator(=) pre_type(array)operator(()delimiter(')string(quick)delimiter(')operator(,) delimiter(')string(brown)delimiter(')operator(,) delimiter(')string(fox)delimiter(')operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($a) operator(=) ident(escapeshellarg)operator(()delimiter(')string(Why are you teasing me?)delimiter(')operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($lines) operator(=) delimiter(<<<END_OF_HERE_DOC)
+ constant(The) ident(boy) ident(stood) ident(on) ident(the) ident(burning) ident(deck)operator(,)
+ ident(it) ident(was) reserved(as) ident(hot) reserved(as) ident(glass)operator(.)
+constant(END_OF_HERE_DOC)operator(;)
+
+comment(// ------------)
+
+local_variable($bigarray) operator(=) ident(array_map)operator(()delimiter(')string(rtrim)delimiter(')operator(,) ident(file)operator(()delimiter(')string(mydatafile)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($banner) operator(=) delimiter(')string(The mines of Moria)delimiter(')operator(;)
+
+local_variable($banner) operator(=) ident(escapeshellarg)operator(()delimiter(')string(The mines of Moria)delimiter(')operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($name) operator(=) delimiter(')string(Gandalf)delimiter(')operator(;)
+
+local_variable($banner) operator(=) delimiter(")string(Speak )operator({)local_variable($name)operator(})string(, and enter!)delimiter(")operator(;)
+
+local_variable($banner) operator(=) delimiter(')string(Speak )delimiter(') operator(.) ident(escapeshellarg)operator(()local_variable($name)operator(\)) operator(.) delimiter(')string( and welcome!)delimiter(')operator(;)
+
+comment(// ------------)
+
+local_variable($his_host) operator(=) delimiter(')string(www.perl.com)delimiter(')operator(;)
+
+local_variable($host_info) operator(=) error(`)ident(nslookup) local_variable($his_host)error(`)operator(;)
+
+local_variable($cmd) operator(=) delimiter(')string(ps )delimiter(') operator(.) ident(posix_getpid)operator(()operator(\))operator(;) local_variable($perl_info) operator(=) error(`)local_variable($cmd)error(`)operator(;)
+
+local_variable($shell_info) operator(=) error(`)ident(ps) error($)error($)error(`)operator(;)
+
+comment(// ------------)
+
+local_variable($banner) operator(=) pre_type(array)operator(()delimiter(')string(Costs)delimiter(')operator(,) delimiter(')string(only)delimiter(')operator(,) delimiter(')string($4.95)delimiter(')operator(\))operator(;)
+
+local_variable($banner) operator(=) ident(array_map)operator(()delimiter(')string(escapeshellarg)delimiter(')operator(,) ident(split)operator(()delimiter(')string( )delimiter(')operator(,) delimiter(')string(Costs only $4.95)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// ------------)
+
+comment(// AFAIK PHP doesn't support non-quoted strings ala Perl's 'q', 'qq' and 'qw', so arrays)
+comment(// created from strings must use quoted strings, and make use of 'split' [or equivalent].)
+comment(// A slew of functions exist for performing string quoting, including 'escapeshellarg',)
+comment(// 'quotemeta', and 'preg_quote')
+
+local_variable($brax) operator(=) ident(split)operator(()delimiter(')string( )delimiter(')operator(,) delimiter(')string(( \) < > { } [ ])delimiter(')operator(\))operator(;)
+
+comment(// Do this to quote each element within '..')
+comment(// $brax = array_map('escapeshellarg', split(' ', '( \) < > { } [ ]'\)\);)
+
+local_variable($rings) operator(=) ident(split)operator(()delimiter(')string( )delimiter(')operator(,) delimiter(')string(Nenya Narya Vilya)delimiter(')operator(\))operator(;)
+
+local_variable($tags) operator(=) ident(split)operator(()delimiter(')string( )delimiter(')operator(,) delimiter(')string(LI TABLE TR TD A IMG H1 P)delimiter(')operator(\))operator(;)
+
+local_variable($sample) operator(=) ident(split)operator(()delimiter(')string( )delimiter(')operator(,) delimiter(')string(The vertical bar | looks and behaves like a pipe.)delimiter(')operator(\))operator(;)
+
+comment(// @@PLEAC@@_4.2)
+pre_type(function) ident(commify_series)operator(()local_variable($list)operator(\))
+operator({)
+ local_variable($n) operator(=) ident(str_word_count)operator(()local_variable($list)operator(\))operator(;) local_variable($series) operator(=) ident(str_word_count)operator(()local_variable($list)operator(,) integer(1)operator(\))operator(;)
+
+ reserved(if) operator(()local_variable($n) operator(==) integer(0)operator(\)) reserved(return) constant(NULL)operator(;)
+ reserved(if) operator(()local_variable($n) operator(==) integer(1)operator(\)) reserved(return) local_variable($series)operator([)integer(0)operator(])operator(;)
+ reserved(if) operator(()local_variable($n) operator(==) integer(2)operator(\)) reserved(return) local_variable($series)operator([)integer(0)operator(]) operator(.) delimiter(')string( and )delimiter(') operator(.) local_variable($series)operator([)integer(1)operator(])operator(;)
+
+ reserved(return) ident(join)operator(()delimiter(')string(, )delimiter(')operator(,) ident(array_slice)operator(()local_variable($series)operator(,) integer(0)operator(,) integer(-1)operator(\))operator(\)) operator(.) delimiter(')string(, and )delimiter(') operator(.) local_variable($series)operator([)local_variable($n) operator(-) integer(1)operator(])operator(;)
+operator(})
+
+comment(// ------------)
+
+pre_type(echo) ident(commify_series)operator(()delimiter(')string(red)delimiter(')operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+pre_type(echo) ident(commify_series)operator(()delimiter(')string(red yellow)delimiter(')operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+pre_type(echo) ident(commify_series)operator(()delimiter(')string(red yellow green)delimiter(')operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+local_variable($mylist) operator(=) delimiter(')string(red yellow green)delimiter(')operator(;)
+pre_type(echo) delimiter(')string(I have )delimiter(') operator(.) ident(commify_series)operator(()local_variable($mylist)operator(\)) operator(.) delimiter(")string( marbles.)char(\\n)delimiter(")operator(;)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(commify_series)operator(()local_variable($arr)operator(\))
+operator({)
+ local_variable($n) operator(=) ident(count)operator(()local_variable($arr)operator(\))operator(;) local_variable($sepchar) operator(=) delimiter(')string(,)delimiter(')operator(;)
+
+ reserved(foreach)operator(()local_variable($arr) reserved(as) local_variable($str)operator(\))
+ operator({)
+ reserved(if) operator(()ident(strpos)operator(()local_variable($str)operator(,) delimiter(')string(,)delimiter(')operator(\)) operator(===) pre_type(false)operator(\)) reserved(continue)operator(;)
+ local_variable($sepchar) operator(=) delimiter(')string(;)delimiter(')operator(;) reserved(break)operator(;)
+ operator(})
+
+ reserved(if) operator(()local_variable($n) operator(==) integer(0)operator(\)) reserved(return) constant(NULL)operator(;)
+ reserved(if) operator(()local_variable($n) operator(==) integer(1)operator(\)) reserved(return) local_variable($arr)operator([)integer(0)operator(])operator(;)
+ reserved(if) operator(()local_variable($n) operator(==) integer(2)operator(\)) reserved(return) local_variable($arr)operator([)integer(0)operator(]) operator(.) delimiter(')string( and )delimiter(') operator(.) local_variable($arr)operator([)integer(1)operator(])operator(;)
+
+ reserved(return) ident(join)operator(()delimiter(")operator({)local_variable($sepchar)operator(})string( )delimiter(")operator(,) ident(array_slice)operator(()local_variable($arr)operator(,) integer(0)operator(,) integer(-1)operator(\))operator(\)) operator(.) delimiter(")operator({)local_variable($sepchar)operator(})string( and )delimiter(") operator(.) local_variable($arr)operator([)local_variable($n) operator(-) integer(1)operator(])operator(;)
+operator(})
+
+comment(// ------------)
+
+local_variable($lists) operator(=) pre_type(array)operator(()
+ pre_type(array)operator(()delimiter(')string(just one thing)delimiter(')operator(\))operator(,)
+ ident(split)operator(()delimiter(')string( )delimiter(')operator(,) delimiter(')string(Mutt Jeff)delimiter(')operator(\))operator(,)
+ ident(split)operator(()delimiter(')string( )delimiter(')operator(,) delimiter(')string(Peter Paul Mary)delimiter(')operator(\))operator(,)
+ pre_type(array)operator(()delimiter(')string(To our parents)delimiter(')operator(,) delimiter(')string(Mother Theresa)delimiter(')operator(,) delimiter(')string(God)delimiter(')operator(\))operator(,)
+ pre_type(array)operator(()delimiter(')string(pastrami)delimiter(')operator(,) delimiter(')string(ham and cheese)delimiter(')operator(,) delimiter(')string(peanut butter and jelly)delimiter(')operator(,) delimiter(')string(tuna)delimiter(')operator(\))operator(,)
+ pre_type(array)operator(()delimiter(')string(recycle tired, old phrases)delimiter(')operator(,) delimiter(')string(ponder big, happy thoughts)delimiter(')operator(\))operator(,)
+ pre_type(array)operator(()delimiter(')string(recycle tired, old phrases)delimiter(')operator(,) delimiter(')string(ponder big, happy thoughts)delimiter(')operator(,) delimiter(')string(sleep and dream peacefully)delimiter(')operator(\))operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($lists) reserved(as) local_variable($arr)operator(\))
+operator({)
+ pre_type(echo) delimiter(')string(The list is: )delimiter(') operator(.) ident(commify_series)operator(()local_variable($arr)operator(\)) operator(.) delimiter(")string(.)char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// @@PLEAC@@_4.3)
+comment(// AFAICT you cannot grow / shrink an array to an arbitrary size. However, you can:)
+comment(// * Grow an array by appending an element using subscrip notation, or using)
+comment(// either 'array_unshift' or 'array_push' to add one or more elements)
+
+local_variable($arr)operator([)operator(]) operator(=) delimiter(')string(one)delimiter(')operator(;)
+ident(array_unshift)operator(()local_variable($arr)operator(,) delimiter(')string(one)delimiter(')operator(,) delimiter(')string(two)delimiter(')operator(,) delimiter(')string(three)delimiter(')operator(\))operator(;)
+ident(array_push)operator(()local_variable($arr)operator(,) delimiter(')string(one)delimiter(')operator(,) delimiter(')string(two)delimiter(')operator(,) delimiter(')string(three)delimiter(')operator(\))operator(;)
+
+comment(// * Shrink an array by using 'unset' to remove one or more specific elements, or)
+comment(// either 'array_shift' or 'array_pop' to remove an element from the ends)
+
+pre_type(unset)operator(()local_variable($arr)operator([)local_variable($idx1)operator(])operator(,) local_variable($arr)operator([)local_variable($idx2)operator(])operator(,) local_variable($arr)operator([)local_variable($idx3)operator(])operator(\))operator(;)
+local_variable($item) operator(=) ident(array_shift)operator(()local_variable($arr)operator(\))operator(;)
+local_variable($item) operator(=) ident(array_pop)operator(()local_variable($arr)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(what_about_the_array)operator(()operator(\))
+operator({)
+ pre_type(global) local_variable($people)operator(;)
+
+ pre_type(echo) delimiter(')string(The array now has )delimiter(') operator(.) ident(count)operator(()local_variable($people)operator(\)) operator(.) delimiter(")string( elements)char(\\n)delimiter(")operator(;)
+ pre_type(echo) delimiter(')string(The index value of the last element is )delimiter(') operator(.) operator(()ident(count)operator(()local_variable($people)operator(\)) operator(-) integer(1)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+ pre_type(echo) delimiter(')string(Element #3 is )delimiter(') operator(.) local_variable($people)operator([)integer(3)operator(]) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+operator(})
+
+local_variable($people) operator(=) pre_type(array)operator(()delimiter(')string(Crosby)delimiter(')operator(,) delimiter(')string(Stills)delimiter(')operator(,) delimiter(')string(Nash)delimiter(')operator(,) delimiter(')string(Young)delimiter(')operator(\))operator(;)
+ident(what_about_the_array)operator(()operator(\))operator(;)
+
+ident(array_pop)operator(()local_variable($people)operator(\))operator(;)
+ident(what_about_the_array)operator(()operator(\))operator(;)
+
+comment(// Cannot, AFAICT, resize the array to an arbitrary size)
+
+comment(# @@PLEAC@@_4.4)
+reserved(foreach) operator(()local_variable($list) reserved(as) local_variable($item)operator(\)) operator({)
+ comment(// do something with $item)
+operator(})
+
+comment(// Environment listing example)
+
+comment(// PHP defines a superglobal $_ENV to provide access to environment)
+comment(// variables.)
+
+comment(// Beware, array assignment means copying in PHP. You need to use)
+comment(// the reference operator to avoid copying. But we want a copy here.)
+local_variable($env) operator(=) local_variable($_ENV)operator(;)
+
+comment(// PHP can sort an array by key, so you don't need to get keys,)
+comment(// and then sort.)
+ident(ksort)operator(()local_variable($env)operator(\))operator(;)
+
+reserved(foreach) operator(()local_variable($env) reserved(as) local_variable($key) operator(=>) local_variable($value)operator(\)) operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($key)operator(})string(=)operator({)local_variable($value)operator(})char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// Literal translation of Perl example would be:)
+local_variable($keys) operator(=) ident(array_keys)operator(()local_variable($_ENV)operator(\))operator(;)
+ident(sort)operator(()local_variable($keys)operator(\))operator(;)
+reserved(foreach) operator(()local_variable($keys) reserved(as) local_variable($key)operator(\)) operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($key)operator(})string(=)operator({)local_variable($_ENV)operator([)local_variable($key)operator(])operator(})char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// This assumes that MAX_QUOTA is a named constant.)
+reserved(foreach) operator(()local_variable($all_users) reserved(as) local_variable($user)operator(\)) operator({)
+ local_variable($disk_space) operator(=) ident(get_usage)operator(()local_variable($user)operator(\))operator(;)
+ reserved(if) operator(()local_variable($disk_space) operator(>) constant(MAX_QUOTA)operator(\)) operator({)
+ ident(complain)operator(()local_variable($user)operator(\))operator(;)
+ operator(})
+operator(})
+
+comment(// You can't modify array's elements in-place.)
+local_variable($array) operator(=) pre_type(array)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(\))operator(;)
+local_variable($newarray) operator(=) pre_type(array)operator(()operator(\))operator(;)
+reserved(foreach) operator(()local_variable($array) reserved(as) local_variable($item)operator(\)) operator({)
+ local_variable($newarray)operator([)operator(]) operator(=) local_variable($item) operator(-) integer(1)operator(;)
+operator(})
+ident(print_r)operator(()local_variable($newarray)operator(\))operator(;)
+
+comment(// Before PHP 5, that is. You can precede the reference operator)
+comment(// before $item to get reference instead of copy.)
+local_variable($array) operator(=) pre_type(array)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(\))operator(;)
+reserved(foreach) operator(()local_variable($array) reserved(as) operator(&)local_variable($item)operator(\)) operator({)
+ local_variable($item)operator(--)operator(;)
+operator(})
+ident(print_r)operator(()local_variable($array)operator(\))operator(;)
+
+comment(// TODO: explain the old each(\) and list(\) iteration construct.)
+comment(// foreach is new in PHP 4, and there are subtle differences.)
+
+comment(// @@PLEAC@@_4.5)
+comment(// Conventional 'read-only' access)
+reserved(foreach)operator(()local_variable($array) reserved(as) local_variable($item)operator(\))
+operator({)
+ operator(;) comment(// Can access, but not update, array element referred to by '$item')
+operator(})
+
+comment(// ----)
+
+comment(// '&' makes '$item' a reference)
+reserved(foreach)operator(()local_variable($array) reserved(as) operator(&)local_variable($item)operator(\))
+operator({)
+ operator(;) comment(// Update array element referred to by '$item')
+operator(})
+
+comment(// ------------)
+
+local_variable($arraylen) operator(=) ident(count)operator(()local_variable($array)operator(\))operator(;)
+
+reserved(for)operator(()local_variable($i) operator(=) integer(0)operator(;) local_variable($i) operator(<) local_variable($arraylen)operator(;) local_variable($i)operator(++)operator(\))
+operator({)
+ operator(;) comment(// '$array' is updateable via subscript notation)
+operator(})
+
+comment(// ----------------------------)
+
+local_variable($fruits) operator(=) pre_type(array)operator(()delimiter(')string(Apple)delimiter(')operator(,) delimiter(')string(Raspberry)delimiter(')operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($fruits) reserved(as) operator(&)local_variable($fruit)operator(\))
+operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($fruit)operator(})string( tastes good in a pie.)char(\\n)delimiter(")operator(;)
+operator(})
+
+local_variable($fruitlen) operator(=) ident(count)operator(()local_variable($fruits)operator(\))operator(;)
+
+reserved(for)operator(()local_variable($i) operator(=) integer(0)operator(;) local_variable($i) operator(<) local_variable($fruitlen)operator(;) local_variable($i)operator(++)operator(\))
+operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($fruits)operator([)local_variable($i)operator(])operator(})string( tastes good in a pie.)char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// ----------------------------)
+
+local_variable($rogue_cats) operator(=) pre_type(array)operator(()delimiter(')string(Blackie)delimiter(')operator(,) delimiter(')string(Goldie)delimiter(')operator(,) delimiter(')string(Silkie)delimiter(')operator(\))operator(;)
+
+comment(// Take care to assign reference to '$rogue_cats' array via '=&')
+local_variable($namelist)operator([)delimiter(')string(felines)delimiter(')operator(]) operator(=)operator(&) local_variable($rogue_cats)operator(;)
+
+comment(// Take care to make '$cat' a reference via '&$' to allow updating)
+reserved(foreach)operator(()local_variable($namelist)operator([)delimiter(')string(felines)delimiter(')operator(]) reserved(as) operator(&)local_variable($cat)operator(\))
+operator({)
+ local_variable($cat) operator(.)operator(=) delimiter(')string( [meow])delimiter(')operator(;)
+operator(})
+
+comment(// Via array reference)
+reserved(foreach)operator(()local_variable($namelist)operator([)delimiter(')string(felines)delimiter(')operator(]) reserved(as) local_variable($cat)operator(\))
+operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($cat)operator(})string( purrs hypnotically.)char(\\n)delimiter(")operator(;)
+operator(})
+
+pre_type(echo) delimiter(")string(---)char(\\n)delimiter(")operator(;)
+
+comment(// Original array)
+reserved(foreach)operator(()local_variable($rogue_cats) reserved(as) local_variable($cat)operator(\))
+operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($cat)operator(})string( purrs hypnotically.)char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// @@PLEAC@@_4.6)
+comment(// PHP offers the 'array_unique' function to perform this task. It works with both keyed,)
+comment(// and numerically-indexed arrays; keys / indexes are preserved; use of 'array_values' )
+comment(// is recommended to reindex numerically-indexed arrays since there will likely be missing)
+comment(// indexes)
+
+comment(// Remove duplicate values)
+local_variable($unique) operator(=) ident(array_unique)operator(()local_variable($array)operator(\))operator(;)
+
+comment(// Remove duplicates, and reindex [for numerically-indexed arrays only])
+local_variable($unique) operator(=) ident(array_values)operator(()ident(array_unique)operator(()local_variable($array)operator(\))operator(\))operator(;)
+
+comment(// or use:)
+local_variable($unique) operator(=) ident(array_keys)operator(()ident(array_flip)operator(()local_variable($array)operator(\))operator(\))operator(;)
+
+comment(// ----------------------------)
+
+comment(// Selected Perl 'seen' examples)
+reserved(foreach)operator(()local_variable($list) reserved(as) local_variable($item)operator(\))
+operator({)
+ reserved(if) operator(()operator(!)pre_type(isset)operator(()local_variable($seen)operator([)local_variable($item)operator(])operator(\))operator(\))
+ operator({)
+ local_variable($seen)operator([)local_variable($item)operator(]) operator(=) constant(TRUE)operator(;)
+ local_variable($unique)operator([)operator(]) operator(=) local_variable($item)operator(;)
+ operator(})
+operator(})
+
+comment(// ------------)
+
+reserved(foreach)operator(()local_variable($list) reserved(as) local_variable($item)operator(\))
+operator({)
+ local_variable($seen)operator([)local_variable($item)operator(]) operator(|)operator(|) operator(()operator(++)local_variable($seen)operator([)local_variable($item)operator(]) operator(&)operator(&) operator(()local_variable($unique)operator([)operator(]) operator(=) local_variable($item)operator(\))operator(\))operator(;)
+operator(})
+
+comment(// ------------)
+
+pre_type(function) ident(some_func)operator(()local_variable($item)operator(\))
+operator({)
+ operator(;) comment(// Do something with '$item')
+operator(})
+
+reserved(foreach)operator(()local_variable($list) reserved(as) local_variable($item)operator(\))
+operator({)
+ local_variable($seen)operator([)local_variable($item)operator(]) operator(|)operator(|) operator(()operator(++)local_variable($seen)operator([)local_variable($item)operator(]) operator(&)operator(&) ident(some_func)operator(()local_variable($item)operator(\))operator(\))operator(;)
+operator(})
+
+comment(// ----------------------------)
+
+reserved(foreach)operator(()ident(array_slice)operator(()ident(preg_split)operator(()delimiter(')string(/)string(\\)string(n/)delimiter(')operator(,) error(`)ident(who)error(`)operator(\))operator(,) integer(0)operator(,) integer(-1)operator(\)) reserved(as) local_variable($user_entry)operator(\))
+operator({)
+ local_variable($user) operator(=) ident(preg_split)operator(()delimiter(')string(/)string(\\)string(s/)delimiter(')operator(,) local_variable($user_entry)operator(\))operator(;)
+ local_variable($ucnt)operator([)local_variable($user)operator([)integer(0)operator(])operator(])operator(++)operator(;)
+operator(})
+
+ident(ksort)operator(()local_variable($ucnt)operator(\))operator(;)
+
+pre_type(echo) delimiter(")string(users logged in:)char(\\n)delimiter(")operator(;)
+
+reserved(foreach)operator(()local_variable($ucnt) reserved(as) local_variable($user) operator(=>) local_variable($cnt)operator(\))
+operator({)
+ pre_type(echo) delimiter(")char(\\t)operator({)local_variable($user)operator(})string( => )operator({)local_variable($cnt)operator(})char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// @@PLEAC@@_4.7)
+comment(// PHP offers the 'array_diff' and 'array_diff_assoc' functions to perform this task. Same)
+comment(// points as made about 'array_unique' apply here also)
+
+local_variable($a) operator(=) pre_type(array)operator(()delimiter(')string(c)delimiter(')operator(,) delimiter(')string(a)delimiter(')operator(,) delimiter(')string(b)delimiter(')operator(,) delimiter(')string(d)delimiter(')operator(\))operator(;)
+local_variable($b) operator(=) pre_type(array)operator(()delimiter(')string(c)delimiter(')operator(,) delimiter(')string(a)delimiter(')operator(,) delimiter(')string(b)delimiter(')operator(,) delimiter(')string(e)delimiter(')operator(\))operator(;)
+
+local_variable($diff) operator(=) ident(array_diff)operator(()local_variable($a)operator(,) local_variable($b)operator(\))operator(;) comment(// $diff -> [3] 'd')
+local_variable($diff) operator(=) ident(array_diff)operator(()local_variable($b)operator(,) local_variable($a)operator(\))operator(;) comment(// $diff -> [3] 'e')
+
+comment(// Numerically-indexed array, reindexed)
+local_variable($diff) operator(=) ident(array_values)operator(()ident(array_diff)operator(()local_variable($a)operator(,) local_variable($b)operator(\))operator(\))operator(;) comment(// $diff -> [0] 'd')
+local_variable($diff) operator(=) ident(array_values)operator(()ident(array_diff)operator(()local_variable($b)operator(,) local_variable($a)operator(\))operator(\))operator(;) comment(// $diff -> [0] 'e')
+
+comment(// ----------------------------)
+
+comment(// 1st Perl 'seen' example only)
+
+local_variable($a) operator(=) pre_type(array)operator(()delimiter(')string(k1)delimiter(') operator(=>) integer(11)operator(,) delimiter(')string(k2)delimiter(') operator(=>) integer(12)operator(,) delimiter(')string(k4)delimiter(') operator(=>) integer(14)operator(\))operator(;)
+local_variable($b) operator(=) pre_type(array)operator(()delimiter(')string(k1)delimiter(') operator(=>) integer(11)operator(,) delimiter(')string(k2)delimiter(') operator(=>) integer(12)operator(,) delimiter(')string(k3)delimiter(') operator(=>) integer(13)operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($b) reserved(as) local_variable($item) operator(=>) local_variable($value)operator(\)) operator({) local_variable($seen)operator([)local_variable($item)operator(]) operator(=) integer(1)operator(;) operator(})
+
+comment(// Stores key only e.g. $aonly[0] contains 'k4', same as Perl example)
+reserved(foreach)operator(()local_variable($a) reserved(as) local_variable($item) operator(=>) local_variable($value)operator(\)) operator({) reserved(if) operator(()operator(!)local_variable($seen)operator([)local_variable($item)operator(])operator(\)) local_variable($aonly)operator([)operator(]) operator(=) local_variable($item)operator(;) operator(})
+
+comment(// Stores key and value e.g. $aonly['k4'] contains 14, same entry as in $a)
+reserved(foreach)operator(()local_variable($a) reserved(as) local_variable($item) operator(=>) local_variable($value)operator(\)) operator({) reserved(if) operator(()operator(!)local_variable($seen)operator([)local_variable($item)operator(])operator(\)) local_variable($aonly)operator([)local_variable($item)operator(]) operator(=) local_variable($value)operator(;) operator(})
+
+comment(// ----------------------------)
+
+comment(// Conventional way: $hash = array('key1' => 1, 'key2' => 2\);)
+
+local_variable($hash)operator([)delimiter(')string(key1)delimiter(')operator(]) operator(=) integer(1)operator(;)
+local_variable($hash)operator([)delimiter(')string(key2)delimiter(')operator(]) operator(=) integer(2)operator(;)
+
+local_variable($hash) operator(=) ident(array_combine)operator(()pre_type(array)operator(()delimiter(')string(key1)delimiter(')operator(,) delimiter(')string(key2)delimiter(')operator(\))operator(,) pre_type(array)operator(()integer(1)operator(,) integer(2)operator(\))operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($seen) operator(=) ident(array_slice)operator(()local_variable($b)operator(,) integer(0)operator(\))operator(;)
+
+local_variable($seen) operator(=) ident(array_combine)operator(()ident(array_keys)operator(()local_variable($b)operator(\))operator(,) ident(array_fill)operator(()integer(0)operator(,) ident(count)operator(()local_variable($b)operator(\))operator(,) integer(1)operator(\))operator(\))operator(;)
+
+comment(// @@PLEAC@@_4.8)
+comment(// PHP offers a number of array-based 'set operation' functions:)
+comment(// * union: array_unique(array_merge(...\)\))
+comment(// * intersection: array_intersect and family)
+comment(// * difference: array_diff and family)
+comment(// which may be used for this type of task. Also, if returned arrays need to be)
+comment(// reindexed, 'array_slice($array, 0\)', or 'array_values($array\)' are useful)
+
+local_variable($a) operator(=) pre_type(array)operator(()integer(1)operator(,) integer(3)operator(,) integer(5)operator(,) integer(6)operator(,) integer(7)operator(,) integer(8)operator(\))operator(;)
+local_variable($b) operator(=) pre_type(array)operator(()integer(2)operator(,) integer(3)operator(,) integer(5)operator(,) integer(7)operator(,) integer(9)operator(\))operator(;)
+
+local_variable($union) operator(=) ident(array_values)operator(()ident(array_unique)operator(()ident(array_merge)operator(()local_variable($a)operator(,) local_variable($b)operator(\))operator(\))operator(\))operator(;) comment(// 1, 2, 3, 5, 6, 7, 8, 9)
+local_variable($isect) operator(=) ident(array_values)operator(()ident(array_intersect)operator(()local_variable($a)operator(,) local_variable($b)operator(\))operator(\))operator(;) comment(// 3, 5, 7)
+local_variable($diff) operator(=) ident(array_values)operator(()ident(array_diff)operator(()local_variable($a)operator(,) local_variable($b)operator(\))operator(\))operator(;) comment(// 1, 8)
+
+comment(// @@PLEAC@@_4.9)
+comment(// PHP offers the 'array_merge' function to perform this task. Duplicate values are retained,)
+comment(// but if arrays are numerically-indexed, resulting array is reindexed)
+
+local_variable($arr1) operator(=) pre_type(array)operator(()delimiter(')string(c)delimiter(')operator(,) delimiter(')string(a)delimiter(')operator(,) delimiter(')string(b)delimiter(')operator(,) delimiter(')string(d)delimiter(')operator(\))operator(;)
+local_variable($arr2) operator(=) pre_type(array)operator(()delimiter(')string(c)delimiter(')operator(,) delimiter(')string(a)delimiter(')operator(,) delimiter(')string(b)delimiter(')operator(,) delimiter(')string(e)delimiter(')operator(\))operator(;)
+
+local_variable($new) operator(=) ident(array_merge)operator(()local_variable($arr1)operator(,) local_variable($arr2)operator(\))operator(;) comment(// $new -> 'c', 'a', 'b', 'd', 'c', 'a', 'b', 'd')
+
+comment(// ----------------------------)
+
+local_variable($members) operator(=) pre_type(array)operator(()delimiter(')string(Time)delimiter(')operator(,) delimiter(')string(Flies)delimiter(')operator(\))operator(;)
+local_variable($initiates) operator(=) pre_type(array)operator(()delimiter(')string(An)delimiter(')operator(,) delimiter(')string(Arrow)delimiter(')operator(\))operator(;)
+
+local_variable($members) operator(=) ident(array_merge)operator(()local_variable($members)operator(,) local_variable($initiates)operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($members) operator(=) pre_type(array)operator(()delimiter(')string(Time)delimiter(')operator(,) delimiter(')string(Flies)delimiter(')operator(\))operator(;)
+local_variable($initiates) operator(=) pre_type(array)operator(()delimiter(')string(An)delimiter(')operator(,) delimiter(')string(Arrow)delimiter(')operator(\))operator(;)
+
+comment(// 'array_splice' is the PHP equivalent to Perl's 'splice')
+ident(array_splice)operator(()local_variable($members)operator(,) integer(2)operator(,) integer(0)operator(,) ident(array_merge)operator(()pre_type(array)operator(()delimiter(')string(Like)delimiter(')operator(\))operator(,) local_variable($initiates)operator(\))operator(\))operator(;)
+pre_type(echo) ident(join)operator(()delimiter(')string( )delimiter(')operator(,) local_variable($members)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+ident(array_splice)operator(()local_variable($members)operator(,) integer(0)operator(,) integer(1)operator(,) pre_type(array)operator(()delimiter(')string(Fruit)delimiter(')operator(\))operator(\))operator(;)
+ident(array_splice)operator(()local_variable($members)operator(,) integer(-2)operator(,) integer(2)operator(,) pre_type(array)operator(()delimiter(')string(A)delimiter(')operator(,) delimiter(')string(Banana)delimiter(')operator(\))operator(\))operator(;)
+pre_type(echo) ident(join)operator(()delimiter(')string( )delimiter(')operator(,) local_variable($members)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// @@PLEAC@@_4.10)
+local_variable($reversed) operator(=) ident(array_reverse)operator(()local_variable($array)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+reserved(foreach)operator(()ident(array_reverse)operator(()local_variable($array)operator(\)) reserved(as) local_variable($item)operator(\))
+operator({)
+ operator(;) comment(// ... do something with '$item' ...)
+operator(})
+
+comment(// ------------)
+
+reserved(for)operator(()local_variable($i) operator(=) ident(count)operator(()local_variable($array)operator(\)) operator(-) integer(1)operator(;) local_variable($i) operator(>=) integer(0)operator(;) local_variable($i)operator(--)operator(\))
+operator({)
+ operator(;) comment(// ... do something with '$array[$i]' ...)
+operator(})
+
+comment(// ----------------------------)
+
+ident(sort)operator(()local_variable($array)operator(\))operator(;)
+local_variable($array) operator(=) ident(array_reverse)operator(()local_variable($array)operator(\))operator(;)
+
+comment(// ------------)
+
+ident(rsort)operator(()local_variable($array)operator(\))operator(;)
+
+comment(// @@PLEAC@@_4.11)
+comment(// Array elements can be deleted using 'unset'; removing several elements would require applying)
+comment(// 'unset' several times, probably in a loop. However, they would most likely also need to be)
+comment(// reindexed, so a better approach would be to use 'array_slice' which avoids explicit looping.)
+comment(// Where elements need to be removed, and those elements also returned, it is probably best to)
+comment(// combine both operations in a function. This is the approach taken here in implementing both)
+comment(// 'shiftN' and 'popN', and it is these functions that are used in the examples)
+
+pre_type(function) ident(popN)operator(()operator(&)local_variable($arr)operator(,) local_variable($n)operator(\))
+operator({)
+ local_variable($ret) operator(=) ident(array_slice)operator(()local_variable($arr)operator(,) operator(-)operator(()local_variable($n)operator(\))operator(,) local_variable($n)operator(\))operator(;)
+ local_variable($arr) operator(=) ident(array_slice)operator(()local_variable($arr)operator(,) integer(0)operator(,) ident(count)operator(()local_variable($arr)operator(\)) operator(-) local_variable($n)operator(\))operator(;)
+ reserved(return) local_variable($ret)operator(;)
+operator(})
+
+pre_type(function) ident(shiftN)operator(()operator(&)local_variable($arr)operator(,) local_variable($n)operator(\))
+operator({)
+ local_variable($ret) operator(=) ident(array_slice)operator(()local_variable($arr)operator(,) integer(0)operator(,) local_variable($n)operator(\))operator(;)
+ local_variable($arr) operator(=) ident(array_slice)operator(()local_variable($arr)operator(,) local_variable($n)operator(\))operator(;)
+ reserved(return) local_variable($ret)operator(;)
+operator(})
+
+comment(// ------------)
+
+comment(// Remove $n elements from the front of $array; return them in $fron)
+local_variable($front) operator(=) ident(shiftN)operator(()local_variable($array)operator(,) local_variable($n)operator(\))operator(;)
+
+comment(// Remove $n elements from the end of $array; return them in $end)
+local_variable($end) operator(=) ident(popN)operator(()local_variable($array)operator(,) local_variable($n)operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($friends) operator(=) pre_type(array)operator(()delimiter(')string(Peter)delimiter(')operator(,) delimiter(')string(Paul)delimiter(')operator(,) delimiter(')string(Mary)delimiter(')operator(,) delimiter(')string(Jim)delimiter(')operator(,) delimiter(')string(Tim)delimiter(')operator(\))operator(;)
+
+pre_type(list)operator(()local_variable($this_)operator(,) local_variable($that)operator(\)) operator(=) ident(shiftN)operator(()local_variable($friends)operator(,) integer(2)operator(\))operator(;)
+
+pre_type(echo) delimiter(")operator({)local_variable($this_)operator(})string( )operator({)local_variable($that)operator(})char(\\n)delimiter(")operator(;)
+
+comment(// ------------)
+
+local_variable($beverages) operator(=) pre_type(array)operator(()delimiter(')string(Dew)delimiter(')operator(,) delimiter(')string(Jolt)delimiter(')operator(,) delimiter(')string(Cola)delimiter(')operator(,) delimiter(')string(Sprite)delimiter(')operator(,) delimiter(')string(Fresca)delimiter(')operator(\))operator(;)
+
+local_variable($pair) operator(=) ident(popN)operator(()local_variable($beverages)operator(,) integer(2)operator(\))operator(;)
+
+pre_type(echo) ident(join)operator(()delimiter(')string( )delimiter(')operator(,) local_variable($pair)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// @@PLEAC@@_4.12)
+comment(// This section illustrates various 'find first' techniques. The Perl examples all use an)
+comment(// explicit loop and condition testing [also repeated here]. This is the simplest, and)
+comment(// [potentially] most efficient approach because the search can be terminated as soon as a)
+comment(// match is found. However, it is worth mentioning a few alternatives:)
+comment(// * 'array_search' performs a 'find first' using the element value rather than a condition)
+comment(// check, so isn't really applicable here)
+comment(// * 'array_filter', whilst using a condition check, actually performs a 'find all', though)
+comment(// all but the first returned element can be discarded. This approach is actually less error)
+comment(// prone than using a loop, but the disadvantage is that each element is visited: there is no)
+comment(// means of terminating the search once a match has been found. It would be nice if this)
+comment(// function were to have a third parameter, a Boolean flag indicating whether to traverse)
+comment(// the whole array, or quit after first match [next version, maybe :\) ?])
+
+local_variable($found) operator(=) constant(FALSE)operator(;)
+
+reserved(foreach)operator(()local_variable($array) reserved(as) local_variable($item)operator(\))
+operator({)
+ comment(// Not found - skip to next item)
+ reserved(if) operator(()operator(!)local_variable($criterion)operator(\)) reserved(continue)operator(;)
+
+ comment(// Found - save and leave)
+ local_variable($match) operator(=) local_variable($item)operator(;)
+ local_variable($found) operator(=) constant(TRUE)operator(;)
+ reserved(break)operator(;)
+operator(})
+
+reserved(if) operator(()local_variable($found)operator(\))
+operator({)
+ operator(;) comment(// do something with $match)
+operator(})
+reserved(else)
+operator({)
+ operator(;) comment(// not found)
+operator(})
+
+comment(// ------------)
+
+pre_type(function) ident(predicate)operator(()local_variable($element)operator(\))
+operator({)
+ reserved(if) operator(()ident(criterion)operator(\)) reserved(return) constant(TRUE)operator(;)
+ reserved(return) constant(FALSE)operator(;)
+operator(})
+
+local_variable($match) operator(=) ident(array_slice)operator(()ident(array_filter)operator(()local_variable($array)operator(,) delimiter(')string(predicate)delimiter(')operator(\))operator(,) integer(0)operator(,) integer(1)operator(\))operator(;)
+
+reserved(if) operator(()local_variable($match)operator(\))
+operator({)
+ operator(;) comment(// do something with $match[0])
+operator(})
+reserved(else)
+operator({)
+ operator(;) comment(// $match is empty - not found)
+operator(})
+
+comment(// ----------------------------)
+
+pre_type(class) constant(Employee)
+operator({)
+ pre_type(public) local_variable($name)operator(,) local_variable($age)operator(,) local_variable($ssn)operator(,) local_variable($salary)operator(;)
+
+ pre_type(public) pre_type(function) ident(__construct)operator(()local_variable($name)operator(,) local_variable($age)operator(,) local_variable($ssn)operator(,) local_variable($salary)operator(,) local_variable($category)operator(\))
+ operator({)
+ local_variable($this)operator(->)ident(name) operator(=) local_variable($name)operator(;)
+ local_variable($this)operator(->)ident(age) operator(=) local_variable($age)operator(;)
+ local_variable($this)operator(->)ident(ssn) operator(=) local_variable($ssn)operator(;)
+ local_variable($this)operator(->)ident(salary) operator(=) local_variable($salary)operator(;)
+ local_variable($this)operator(->)ident(category) operator(=) local_variable($category)operator(;)
+ operator(})
+operator(})
+
+comment(// ------------)
+
+local_variable($employees) operator(=) pre_type(array)operator(()
+ pre_type(new) constant(Employee)operator(()delimiter(')string(sdf)delimiter(')operator(,) integer(27)operator(,) integer(12345)operator(,) integer(47000)operator(,) delimiter(')string(Engineer)delimiter(')operator(\))operator(,)
+ pre_type(new) constant(Employee)operator(()delimiter(')string(ajb)delimiter(')operator(,) integer(32)operator(,) integer(12376)operator(,) integer(51000)operator(,) delimiter(')string(Programmer)delimiter(')operator(\))operator(,)
+ pre_type(new) constant(Employee)operator(()delimiter(')string(dgh)delimiter(')operator(,) integer(31)operator(,) integer(12355)operator(,) integer(45000)operator(,) delimiter(')string(Engineer)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// ------------)
+
+pre_type(function) ident(array_update)operator(()local_variable($arr)operator(,) local_variable($lambda)operator(,) local_variable($updarr)operator(\))
+operator({)
+ reserved(foreach)operator(()local_variable($arr) reserved(as) local_variable($key)operator(\)) local_variable($lambda)operator(()local_variable($updarr)operator(,) local_variable($key)operator(\))operator(;)
+ reserved(return) local_variable($updarr)operator(;)
+operator(})
+
+pre_type(function) ident(highest_salaried_engineer)operator(()operator(&)local_variable($arr)operator(,) local_variable($employee)operator(\))
+operator({)
+ pre_type(static) local_variable($highest_salary) operator(=) integer(0)operator(;)
+
+ reserved(if) operator(()local_variable($employee)operator(->)ident(category) operator(==) delimiter(')string(Engineer)delimiter(')operator(\))
+ operator({)
+ reserved(if) operator(()local_variable($employee)operator(->)ident(salary) operator(>) local_variable($highest_salary)operator(\))
+ operator({)
+ local_variable($highest_salary) operator(=) local_variable($employee)operator(->)ident(salary)operator(;)
+ local_variable($arr)operator([)integer(0)operator(]) operator(=) local_variable($employee)operator(;)
+ operator(})
+ operator(})
+operator(})
+
+comment(// ------------)
+
+comment(// 'array_update' custom function is modelled on 'array_reduce' except that it allows the)
+comment(// return of an array, contents and length of which are entirely dependant on what the)
+comment(// callback function does. Here, it is logically working in a 'find first' capacity)
+local_variable($highest_salaried_engineer) operator(=) ident(array_update)operator(()local_variable($employees)operator(,) delimiter(')string(highest_salaried_engineer)delimiter(')operator(,) pre_type(array)operator(()operator(\))operator(\))operator(;)
+
+pre_type(echo) delimiter(')string(Highest paid engineer is: )delimiter(') operator(.) local_variable($highest_salaried_engineer)operator([)integer(0)operator(])operator(->)ident(name) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// @@PLEAC@@_4.13)
+comment(// PHP implements 'grep' functionality [as embodied in the current section] in the 'array_filter')
+comment(// function)
+
+pre_type(function) ident(predicate)operator(()local_variable($element)operator(\))
+operator({)
+ reserved(if) operator(()ident(criterion)operator(\)) reserved(return) constant(TRUE)operator(;)
+ reserved(return) constant(FALSE)operator(;)
+operator(})
+
+local_variable($matching) operator(=) ident(array_filter)operator(()local_variable($list)operator(,) delimiter(')string(predicate)delimiter(')operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($bigs) operator(=) ident(array_filter)operator(()local_variable($nums)operator(,) ident(create_function)operator(()delimiter(')string($n)delimiter(')operator(,) delimiter(')string(return $n > 1000000;)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// ------------)
+
+pre_type(function) ident(is_pig)operator(()local_variable($user)operator(\))
+operator({)
+ local_variable($user_details) operator(=) ident(preg_split)operator(()delimiter(')string(/()string(\\)string(s\)+/)delimiter(')operator(,) local_variable($user)operator(\))operator(;)
+ comment(// Assuming field 5 is the resource being compared)
+ reserved(return) local_variable($user_details)operator([)integer(5)operator(]) operator(>) integer(1)ident(e7)operator(;)
+operator(})
+
+local_variable($pigs) operator(=) ident(array_filter)operator(()ident(array_slice)operator(()ident(preg_split)operator(()delimiter(')string(/)string(\\)string(n/)delimiter(')operator(,) error(`)ident(who) operator(-)ident(u)error(`)operator(\))operator(,) integer(0)operator(,) integer(-1)operator(\))operator(,) delimiter(')string(is_pig)delimiter(')operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($matching) operator(=) ident(array_filter)operator(()ident(array_slice)operator(()ident(preg_split)operator(()delimiter(')string(/)string(\\)string(n/)delimiter(')operator(,) error(`)ident(who)error(`)operator(\))operator(,) integer(0)operator(,) integer(-1)operator(\))operator(,)
+ ident(create_function)operator(()delimiter(')string($user)delimiter(')operator(,) delimiter(')string(return preg_match()char(\\')string(/^gnat /)char(\\')string(, $user\);)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// ------------)
+
+pre_type(class) constant(Employee)
+operator({)
+ pre_type(public) local_variable($name)operator(,) local_variable($age)operator(,) local_variable($ssn)operator(,) local_variable($salary)operator(;)
+
+ pre_type(public) pre_type(function) ident(__construct)operator(()local_variable($name)operator(,) local_variable($age)operator(,) local_variable($ssn)operator(,) local_variable($salary)operator(,) local_variable($category)operator(\))
+ operator({)
+ local_variable($this)operator(->)ident(name) operator(=) local_variable($name)operator(;)
+ local_variable($this)operator(->)ident(age) operator(=) local_variable($age)operator(;)
+ local_variable($this)operator(->)ident(ssn) operator(=) local_variable($ssn)operator(;)
+ local_variable($this)operator(->)ident(salary) operator(=) local_variable($salary)operator(;)
+ local_variable($this)operator(->)ident(category) operator(=) local_variable($category)operator(;)
+ operator(})
+operator(})
+
+comment(// ------------)
+
+local_variable($employees) operator(=) pre_type(array)operator(()
+ pre_type(new) constant(Employee)operator(()delimiter(')string(sdf)delimiter(')operator(,) integer(27)operator(,) integer(12345)operator(,) integer(47000)operator(,) delimiter(')string(Engineer)delimiter(')operator(\))operator(,)
+ pre_type(new) constant(Employee)operator(()delimiter(')string(ajb)delimiter(')operator(,) integer(32)operator(,) integer(12376)operator(,) integer(51000)operator(,) delimiter(')string(Programmer)delimiter(')operator(\))operator(,)
+ pre_type(new) constant(Employee)operator(()delimiter(')string(dgh)delimiter(')operator(,) integer(31)operator(,) integer(12355)operator(,) integer(45000)operator(,) delimiter(')string(Engineer)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($engineers) operator(=) ident(array_filter)operator(()local_variable($employees)operator(,)
+ ident(create_function)operator(()delimiter(')string($employee)delimiter(')operator(,) delimiter(')string(return $employee->category == "Engineer";)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// @@PLEAC@@_4.14)
+comment(// PHP offers a rich set of sorting functions. Key features:)
+comment(// * Inplace sorts; the original array, not a a copy, is sorted)
+comment(// * Separate functions exist for sorting [both ascending and descending order]:)
+comment(// - By value, assign new keys / indices [sort, rsort])
+comment(// - By key [ksort, krsort] (for non-numerically indexed arrays\))
+comment(// - By value [asort, arsort])
+comment(// - As above, but using a user-defined comparator [i.e. callback function])
+comment(// [usort, uasort, uksort])
+comment(// - Natural order sort [natsort])
+comment(// * Significantly, if sorting digit-only elements, whether strings or numbers,)
+comment(// 'natural order' [i.e. 1 before 10 before 100 (ascending\)] is retained. If)
+comment(// the elements are alphanumeric e.g. 'z1', 'z10' then 'natsort' should be)
+comment(// used [note: beware of 'natsort' with negative numbers; prefer 'sort' or 'asort'])
+
+local_variable($unsorted) operator(=) pre_type(array)operator(()integer(7)operator(,) integer(12)operator(,) integer(-13)operator(,) integer(2)operator(,) integer(100)operator(,) integer(5)operator(,) integer(1)operator(,) integer(-2)operator(,) integer(23)operator(,) integer(3)operator(,) integer(6)operator(,) integer(4)operator(\))operator(;)
+
+ident(sort)operator(()local_variable($unsorted)operator(\))operator(;) comment(// -13, -2, 1, 2, 3, 4, 5, 6, 7, 12, 23, 100)
+ident(rsort)operator(()local_variable($unsorted)operator(\))operator(;) comment(// 100, 23, 12, 7, 6, 5, 4, 3, 2, 1, -2, -13)
+
+ident(asort)operator(()local_variable($unsorted)operator(\))operator(;) comment(// -13, -2, 1, 2, 3, 4, 5, 6, 7, 12, 23, 100)
+ident(arsort)operator(()local_variable($unsorted)operator(\))operator(;) comment(// 100, 23, 12, 7, 6, 5, 4, 3, 2, 1, -2, -13)
+
+ident(natsort)operator(()local_variable($unsorted)operator(\))operator(;) comment(// -2, -13, 1, 2, 3, 4, 5, 6, 7, 12, 23, 100)
+
+comment(// ------------)
+
+pre_type(function) ident(ascend)operator(()local_variable($left)operator(,) local_variable($right)operator(\)) operator({) reserved(return) local_variable($left) operator(>) local_variable($right)operator(;) operator(})
+pre_type(function) ident(descend)operator(()local_variable($left)operator(,) local_variable($right)operator(\)) operator({) reserved(return) local_variable($left) operator(<) local_variable($right)operator(;) operator(})
+
+comment(// ------------)
+
+ident(usort)operator(()local_variable($unsorted)operator(,) delimiter(')string(ascend)delimiter(')operator(\))operator(;) comment(// -13, -2, 1, 2, 3, 4, 5, 6, 7, 12, 23, 100)
+ident(usort)operator(()local_variable($unsorted)operator(,) delimiter(')string(descend)delimiter(')operator(\))operator(;) comment(// 100, 23, 12, 7, 6, 5, 4, 3, 2, 1, -2, -13)
+
+ident(uasort)operator(()local_variable($unsorted)operator(,) delimiter(')string(ascend)delimiter(')operator(\))operator(;) comment(// -13, -2, 1, 2, 3, 4, 5, 6, 7, 12, 23, 100)
+ident(uasort)operator(()local_variable($unsorted)operator(,) delimiter(')string(descend)delimiter(')operator(\))operator(;) comment(// 100, 23, 12, 7, 6, 5, 4, 3, 2, 1, -2, -13)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(kill_process)operator(()local_variable($pid)operator(\))
+operator({)
+ comment(// Is 'killable' ?)
+ reserved(if) operator(()operator(!)ident(posix_kill)operator(()local_variable($pid)operator(,) integer(0)operator(\))operator(\)) reserved(return)operator(;)
+
+ comment(// Ok, so kill in two stages)
+ ident(posix_kill)operator(()local_variable($pid)operator(,) integer(15)operator(\))operator(;) comment(// SIGTERM)
+ ident(sleep)operator(()integer(1)operator(\))operator(;)
+ ident(posix_kill)operator(()local_variable($pid)operator(,) integer(9)operator(\))operator(;) comment(// SIGKILL)
+operator(})
+
+pre_type(function) ident(pid)operator(()local_variable($pentry)operator(\))
+operator({)
+ local_variable($p) operator(=) ident(preg_split)operator(()delimiter(')string(/)string(\\)string(s/)delimiter(')operator(,) ident(trim)operator(()local_variable($pentry)operator(\))operator(\))operator(;)
+ reserved(return) local_variable($p)operator([)integer(0)operator(])operator(;)
+operator(})
+
+local_variable($processes) operator(=) ident(array_map)operator(()delimiter(')string(pid)delimiter(')operator(,) ident(array_slice)operator(()ident(preg_split)operator(()delimiter(')string(/)string(\\)string(n/)delimiter(')operator(,) error(`)ident(ps) ident(ax)error(`)operator(\))operator(,) integer(1)operator(,) integer(-1)operator(\))operator(\))operator(;)
+ident(sort)operator(()local_variable($processes)operator(\))operator(;)
+
+pre_type(echo) ident(join)operator(()delimiter(')string( ,)delimiter(')operator(,) local_variable($processes)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+pre_type(echo) delimiter(')string(Enter a pid to kill: )delimiter(')operator(;)
+reserved(if) operator(()operator(()local_variable($pid) operator(=) ident(trim)operator(()ident(fgets)operator(()constant(STDIN)operator(\))operator(\))operator(\))operator(\))
+ ident(kill_process)operator(()local_variable($pid)operator(\))operator(;)
+
+comment(// @@PLEAC@@_4.15)
+comment(// Tasks in this section would typically use the PHP 'usort' family of functions)
+comment(// which are used with a comparator function so as to perform custom comparisions.)
+comment(// A significant difference from the Perl examples is that these functions are)
+comment(// inplace sorters, so it is the original array that is modified. Where this must)
+comment(// be prevented a copy of the array can be made and sorted)
+
+pre_type(function) ident(comparator)operator(()local_variable($left)operator(,) local_variable($right)operator(\))
+operator({)
+ operator(;) comment(// Compare '$left' with '$right' returning result)
+operator(})
+
+comment(// ------------)
+
+local_variable($ordered) operator(=) ident(array_slice)operator(()local_variable($unordered)operator(\))operator(;)
+ident(usort)operator(()local_variable($ordered)operator(,) delimiter(')string(comparator)delimiter(')operator(\))operator(;)
+
+comment(// ----------------------------)
+
+comment(// The Perl example looks like it is creating a hash using computed values as the key,)
+comment(// array values as the value, sorting on the computed key, then extracting the sorted)
+comment(// values and placing them back into an array)
+
+pre_type(function) ident(compute)operator(()local_variable($value)operator(\))
+operator({)
+ operator(;) comment(// Return computed value utilising '$value')
+operator(})
+
+comment(// ------------)
+
+comment(// Original numerically-indexed array [sample data used])
+local_variable($unordered) operator(=) pre_type(array)operator(()integer(5)operator(,) integer(3)operator(,) integer(7)operator(,) integer(1)operator(,) integer(4)operator(,) integer(2)operator(,) integer(6)operator(\))operator(;)
+
+comment(// Create hash using 'compute' function to generate the keys. This example assumes that)
+comment(// each value in the '$unordered' array is used in generating the corresponding '$key')
+reserved(foreach)operator(()local_variable($unordered) reserved(as) local_variable($value)operator(\))
+operator({)
+ local_variable($precomputed)operator([)ident(compute)operator(()local_variable($value)operator(\))operator(]) operator(=) local_variable($value)operator(;)
+operator(})
+
+comment(// Copy the hash, and sort it by key)
+local_variable($ordered_precomputed) operator(=) ident(array_slice)operator(()local_variable($precomputed)operator(,) integer(0)operator(\))operator(;) ident(ksort)operator(()local_variable($ordered_precomputed)operator(\))operator(;)
+
+comment(// Extract the values of the hash in current order placing them in a new numerically-indexed)
+comment(// array)
+local_variable($ordered) operator(=) ident(array_values)operator(()local_variable($ordered_precomputed)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+comment(// As above, except uses 'array_update' and 'accum' to help create hash)
+
+pre_type(function) ident(array_update)operator(()local_variable($arr)operator(,) local_variable($lambda)operator(,) local_variable($updarr)operator(\))
+operator({)
+ reserved(foreach)operator(()local_variable($arr) reserved(as) local_variable($key)operator(\)) local_variable($lambda)operator(()local_variable($updarr)operator(,) local_variable($key)operator(\))operator(;)
+ reserved(return) local_variable($updarr)operator(;)
+operator(})
+
+pre_type(function) ident(accum)operator(()operator(&)local_variable($arr)operator(,) local_variable($value)operator(\))
+operator({)
+ local_variable($arr)operator([)ident(compute)operator(()local_variable($value)operator(\))operator(]) operator(=) local_variable($value)operator(;)
+operator(})
+
+comment(// ------------)
+
+pre_type(function) ident(compute)operator(()local_variable($value)operator(\))
+operator({)
+ operator(;) comment(// Return computed value utilising '$value')
+operator(})
+
+comment(// ------------)
+
+comment(// Original numerically-indexed array [sample data used])
+local_variable($unordered) operator(=) pre_type(array)operator(()integer(5)operator(,) integer(3)operator(,) integer(7)operator(,) integer(1)operator(,) integer(4)operator(,) integer(2)operator(,) integer(6)operator(\))operator(;)
+
+comment(// Create hash)
+local_variable($precomputed) operator(=) ident(array_update)operator(()local_variable($unordered)operator(,) delimiter(')string(accum)delimiter(')operator(,) pre_type(array)operator(()operator(\))operator(\))operator(;)
+
+comment(// Copy the hash, and sort it by key)
+local_variable($ordered_precomputed) operator(=) ident(array_slice)operator(()local_variable($precomputed)operator(,) integer(0)operator(\))operator(;) ident(ksort)operator(()local_variable($ordered_precomputed)operator(\))operator(;)
+
+comment(// Extract the values of the hash in current order placing them in a new numerically-indexed)
+comment(// array)
+local_variable($ordered) operator(=) ident(array_values)operator(()local_variable($ordered_precomputed)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(class) constant(Employee)
+operator({)
+ pre_type(public) local_variable($name)operator(,) local_variable($age)operator(,) local_variable($ssn)operator(,) local_variable($salary)operator(;)
+
+ pre_type(public) pre_type(function) ident(__construct)operator(()local_variable($name)operator(,) local_variable($age)operator(,) local_variable($ssn)operator(,) local_variable($salary)operator(\))
+ operator({)
+ local_variable($this)operator(->)ident(name) operator(=) local_variable($name)operator(;)
+ local_variable($this)operator(->)ident(age) operator(=) local_variable($age)operator(;)
+ local_variable($this)operator(->)ident(ssn) operator(=) local_variable($ssn)operator(;)
+ local_variable($this)operator(->)ident(salary) operator(=) local_variable($salary)operator(;)
+ operator(})
+operator(})
+
+comment(// ------------)
+
+local_variable($employees) operator(=) pre_type(array)operator(()
+ pre_type(new) constant(Employee)operator(()delimiter(')string(sdf)delimiter(')operator(,) integer(27)operator(,) integer(12345)operator(,) integer(47000)operator(\))operator(,)
+ pre_type(new) constant(Employee)operator(()delimiter(')string(ajb)delimiter(')operator(,) integer(32)operator(,) integer(12376)operator(,) integer(51000)operator(\))operator(,)
+ pre_type(new) constant(Employee)operator(()delimiter(')string(dgh)delimiter(')operator(,) integer(31)operator(,) integer(12355)operator(,) integer(45000)operator(\))operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($ordered) operator(=) ident(array_slice)operator(()local_variable($employees)operator(,) integer(0)operator(\))operator(;)
+ident(usort)operator(()local_variable($ordered)operator(,) ident(create_function)operator(()delimiter(')string($left, $right)delimiter(')operator(,) delimiter(')string(return $left->name > $right->name;)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($sorted_employees) operator(=) ident(array_slice)operator(()local_variable($employees)operator(,) integer(0)operator(\))operator(;)
+ident(usort)operator(()local_variable($sorted_employees)operator(,) ident(create_function)operator(()delimiter(')string($left, $right)delimiter(')operator(,) delimiter(')string(return $left->name > $right->name;)delimiter(')operator(\))operator(\))operator(;)
+
+local_variable($bonus) operator(=) pre_type(array)operator(()integer(12376) operator(=>) integer(5000)operator(,) integer(12345) operator(=>) integer(6000)operator(,) integer(12355) operator(=>) integer(0)operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($sorted_employees) reserved(as) local_variable($employee)operator(\))
+operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($employee)operator(->)ident(name)operator(})string( earns )string(\\)string($)operator({)local_variable($employee)operator(->)ident(salary)operator(})char(\\n)delimiter(")operator(;)
+operator(})
+
+reserved(foreach)operator(()local_variable($sorted_employees) reserved(as) local_variable($employee)operator(\))
+operator({)
+ reserved(if) operator(()operator(()local_variable($amount) operator(=) local_variable($bonus)operator([)local_variable($employee)operator(->)ident(ssn)operator(])operator(\))operator(\))
+ pre_type(echo) delimiter(")operator({)local_variable($employee)operator(->)ident(name)operator(})string( got a bonus of: )string(\\)string($)operator({)local_variable($amount)operator(})char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// ------------)
+
+local_variable($sorted) operator(=) ident(array_slice)operator(()local_variable($employees)operator(,) integer(0)operator(\))operator(;)
+ident(usort)operator(()local_variable($sorted)operator(,) ident(create_function)operator(()delimiter(')string($left, $right)delimiter(')operator(,) delimiter(')string(return $left->name > $right->name || $left->age != $right->age;)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// ----------------------------)
+
+comment(// PHP offers a swag of POSIX functions for obtaining user information [i.e. they all read)
+comment(// the '/etc/passwd' file for the relevant infroamtion], and it is these that should rightly)
+comment(// be used for this purpose. However, since the intent of this section is to illustrate array)
+comment(// manipulation, these functions won't be used. Instead a custom function mimicing Perl's)
+comment(// 'getpwent' function will be implemented so the code presented here can more faithfully match)
+comment(// the Perl code)
+
+pre_type(function) ident(get_pw_entries)operator(()operator(\))
+operator({)
+ pre_type(function) ident(normal_users_only)operator(()local_variable($e)operator(\))
+ operator({)
+ local_variable($entry) operator(=) ident(split)operator(()delimiter(')string(:)delimiter(')operator(,) local_variable($e)operator(\))operator(;) reserved(return) local_variable($entry)operator([)integer(2)operator(]) operator(>) integer(100) operator(&)operator(&) local_variable($entry)operator([)integer(2)operator(]) operator(<) integer(32768)operator(;)
+ operator(})
+
+ reserved(foreach)operator(()ident(array_filter)operator(()ident(file)operator(()delimiter(')string(/etc/passwd)delimiter(')operator(\))operator(,) delimiter(')string(normal_users_only)delimiter(')operator(\)) reserved(as) local_variable($entry)operator(\))
+ local_variable($users)operator([)operator(]) operator(=) ident(split)operator(()delimiter(')string(:)delimiter(')operator(,) ident(trim)operator(()local_variable($entry)operator(\))operator(\))operator(;)
+
+ reserved(return) local_variable($users)operator(;)
+operator(})
+
+comment(// ------------)
+
+local_variable($users) operator(=) ident(get_pw_entries)operator(()operator(\))operator(;)
+
+ident(usort)operator(()local_variable($users)operator(,) ident(create_function)operator(()delimiter(')string($left, $right)delimiter(')operator(,) delimiter(')string(return $left[0] > $right[0];)delimiter(')operator(\))operator(\))operator(;)
+reserved(foreach)operator(()local_variable($users) reserved(as) local_variable($user)operator(\)) pre_type(echo) delimiter(")operator({)local_variable($user)operator([)integer(0)operator(])operator(})char(\\n)delimiter(")operator(;)
+
+comment(// ----------------------------)
+
+local_variable($names) operator(=) pre_type(array)operator(()delimiter(')string(sdf)delimiter(')operator(,) delimiter(')string(ajb)delimiter(')operator(,) delimiter(')string(dgh)delimiter(')operator(\))operator(;)
+
+local_variable($sorted) operator(=) ident(array_slice)operator(()local_variable($names)operator(,) integer(0)operator(\))operator(;)
+ident(usort)operator(()local_variable($sorted)operator(,) ident(create_function)operator(()delimiter(')string($left, $right)delimiter(')operator(,) delimiter(')string(return substr($left, 1, 1\) > substr($right, 1, 1\);)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($strings) operator(=) pre_type(array)operator(()delimiter(')string(bbb)delimiter(')operator(,) delimiter(')string(aa)delimiter(')operator(,) delimiter(')string(c)delimiter(')operator(\))operator(;)
+
+local_variable($sorted) operator(=) ident(array_slice)operator(()local_variable($strings)operator(,) integer(0)operator(\))operator(;)
+ident(usort)operator(()local_variable($sorted)operator(,) ident(create_function)operator(()delimiter(')string($left, $right)delimiter(')operator(,) delimiter(')string(return strlen($left\) > strlen($right\);)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(array_update)operator(()local_variable($arr)operator(,) local_variable($lambda)operator(,) local_variable($updarr)operator(\))
+operator({)
+ reserved(foreach)operator(()local_variable($arr) reserved(as) local_variable($key)operator(\)) local_variable($lambda)operator(()local_variable($updarr)operator(,) local_variable($key)operator(\))operator(;)
+ reserved(return) local_variable($updarr)operator(;)
+operator(})
+
+pre_type(function) ident(accum)operator(()operator(&)local_variable($arr)operator(,) local_variable($value)operator(\))
+operator({)
+ local_variable($arr)operator([)ident(strlen)operator(()local_variable($value)operator(\))operator(]) operator(=) local_variable($value)operator(;)
+operator(})
+
+comment(// ----)
+
+local_variable($strings) operator(=) pre_type(array)operator(()delimiter(')string(bbb)delimiter(')operator(,) delimiter(')string(aa)delimiter(')operator(,) delimiter(')string(c)delimiter(')operator(\))operator(;)
+
+local_variable($temp) operator(=) ident(array_update)operator(()local_variable($strings)operator(,) delimiter(')string(accum)delimiter(')operator(,) pre_type(array)operator(()operator(\))operator(\))operator(;)
+ident(ksort)operator(()local_variable($temp)operator(\))operator(;)
+local_variable($sorted) operator(=) ident(array_values)operator(()local_variable($temp)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(array_update)operator(()local_variable($arr)operator(,) local_variable($lambda)operator(,) local_variable($updarr)operator(\))
+operator({)
+ reserved(foreach)operator(()local_variable($arr) reserved(as) local_variable($key)operator(\)) local_variable($lambda)operator(()local_variable($updarr)operator(,) local_variable($key)operator(\))operator(;)
+ reserved(return) local_variable($updarr)operator(;)
+operator(})
+
+pre_type(function) ident(accum)operator(()operator(&)local_variable($arr)operator(,) local_variable($value)operator(\))
+operator({)
+ reserved(if) operator(()ident(preg_match)operator(()delimiter(')string(/()string(\\)string(d+\)/)delimiter(')operator(,) local_variable($value)operator(,) local_variable($matches)operator(\))operator(\))
+ local_variable($arr)operator([)local_variable($matches)operator([)integer(1)operator(])operator(]) operator(=) local_variable($value)operator(;)
+operator(})
+
+comment(// ----)
+
+local_variable($fields) operator(=) pre_type(array)operator(()delimiter(')string(b1b2b)delimiter(')operator(,) delimiter(')string(a4a)delimiter(')operator(,) delimiter(')string(c9)delimiter(')operator(,) delimiter(')string(ddd)delimiter(')operator(,) delimiter(')string(a)delimiter(')operator(\))operator(;)
+
+local_variable($temp) operator(=) ident(array_update)operator(()local_variable($fields)operator(,) delimiter(')string(accum)delimiter(')operator(,) pre_type(array)operator(()operator(\))operator(\))operator(;)
+ident(ksort)operator(()local_variable($temp)operator(\))operator(;)
+local_variable($sorted_fields) operator(=) ident(array_values)operator(()local_variable($temp)operator(\))operator(;)
+
+comment(// @@PLEAC@@_4.16)
+ident(array_unshift)operator(()local_variable($a1)operator(,) ident(array_pop)operator(()local_variable($a1)operator(\))operator(\))operator(;) comment(// last -> first)
+ident(array_push)operator(()local_variable($a1)operator(,) ident(array_shift)operator(()local_variable($a1)operator(\))operator(\))operator(;) comment(// first -> last)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(grab_and_rotate)operator(()operator(&)local_variable($arr)operator(\))
+operator({)
+ local_variable($item) operator(=) local_variable($arr)operator([)integer(0)operator(])operator(;)
+ ident(array_push)operator(()local_variable($arr)operator(,) ident(array_shift)operator(()local_variable($arr)operator(\))operator(\))operator(;)
+ reserved(return) local_variable($item)operator(;)
+operator(})
+
+comment(// ------------)
+
+local_variable($processes) operator(=) pre_type(array)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(,) integer(4)operator(,) integer(5)operator(\))operator(;)
+
+reserved(while) operator(()constant(TRUE)operator(\))
+operator({)
+ local_variable($process) operator(=) ident(grab_and_rotate)operator(()local_variable($processes)operator(\))operator(;)
+ pre_type(echo) delimiter(")string(Handling process )operator({)local_variable($process)operator(})char(\\n)delimiter(")operator(;)
+ ident(sleep)operator(()integer(1)operator(\))operator(;)
+operator(})
+
+comment(// @@PLEAC@@_4.17)
+comment(// PHP offers the 'shuffle' function to perform this task)
+
+local_variable($arr) operator(=) pre_type(array)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(,) integer(4)operator(,) integer(5)operator(,) integer(6)operator(,) integer(7)operator(,) integer(8)operator(,) integer(9)operator(\))operator(;)
+
+ident(shuffle)operator(()local_variable($arr)operator(\))operator(;)
+
+pre_type(echo) ident(join)operator(()delimiter(')string( )delimiter(')operator(,) local_variable($arr)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// ----------------------------)
+
+comment(// Perl example equivalents)
+pre_type(function) ident(fisher_yates_shuffle)operator(()operator(&)local_variable($a)operator(\))
+operator({)
+ local_variable($size) operator(=) ident(count)operator(()local_variable($a)operator(\)) operator(-) integer(1)operator(;)
+
+ reserved(for)operator(()local_variable($i) operator(=) local_variable($size)operator(;) local_variable($i) operator(>=) integer(0)operator(;) local_variable($i)operator(--)operator(\))
+ operator({)
+ reserved(if) operator(()operator(()local_variable($j) operator(=) ident(rand)operator(()integer(0)operator(,) local_variable($i)operator(\))operator(\)) operator(!=) local_variable($i)operator(\))
+ pre_type(list)operator(()local_variable($a)operator([)local_variable($i)operator(])operator(,) local_variable($a)operator([)local_variable($j)operator(])operator(\)) operator(=) pre_type(array)operator(()local_variable($a)operator([)local_variable($j)operator(])operator(,) local_variable($a)operator([)local_variable($i)operator(])operator(\))operator(;)
+ operator(})
+operator(})
+
+pre_type(function) ident(naive_shuffle)operator(()operator(&)local_variable($a)operator(\))
+operator({)
+ local_variable($size) operator(=) ident(count)operator(()local_variable($a)operator(\))operator(;)
+
+ reserved(for)operator(()local_variable($i) operator(=) integer(0)operator(;) local_variable($i) operator(<) local_variable($size)operator(;) local_variable($i)operator(++)operator(\))
+ operator({)
+ local_variable($j) operator(=) ident(rand)operator(()integer(0)operator(,) local_variable($size) operator(-) integer(1)operator(\))operator(;)
+ pre_type(list)operator(()local_variable($a)operator([)local_variable($i)operator(])operator(,) local_variable($a)operator([)local_variable($j)operator(])operator(\)) operator(=) pre_type(array)operator(()local_variable($a)operator([)local_variable($j)operator(])operator(,) local_variable($a)operator([)local_variable($i)operator(])operator(\))operator(;)
+ operator(})
+operator(})
+
+comment(// ------------)
+
+local_variable($arr) operator(=) pre_type(array)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(,) integer(4)operator(,) integer(5)operator(,) integer(6)operator(,) integer(7)operator(,) integer(8)operator(,) integer(9)operator(\))operator(;)
+
+ident(fisher_yates_shuffle)operator(()local_variable($arr)operator(\))operator(;)
+pre_type(echo) ident(join)operator(()delimiter(')string( )delimiter(')operator(,) local_variable($arr)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+ident(naive_shuffle)operator(()local_variable($arr)operator(\))operator(;)
+pre_type(echo) ident(join)operator(()delimiter(')string( )delimiter(')operator(,) local_variable($arr)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// @@PLEAC@@_4.18)
+comment(// @@INCOMPLETE@@)
+comment(// @@INCOMPLETE@@)
+
+comment(// @@PLEAC@@_4.19)
+comment(// @@INCOMPLETE@@)
+comment(// @@INCOMPLETE@@)
+
+comment(// @@PLEAC@@_5.0)
+comment(// PHP uses the term 'array' to refer to associative arrays - referred to in Perl)
+comment(// as 'hashes' - and for the sake of avoiding confusion, the Perl terminology will)
+comment(// be used. As a matter of interest, PHP does not sport a vector, matrix, or list)
+comment(// type: the 'array' [Perl 'hash'] serves all these roles)
+
+local_variable($age) operator(=) pre_type(array)operator(()delimiter(')string(Nat)delimiter(') operator(=>) integer(24)operator(,) delimiter(')string(Jules)delimiter(') operator(=>) integer(25)operator(,) delimiter(')string(Josh)delimiter(') operator(=>) integer(17)operator(\))operator(;)
+
+local_variable($age)operator([)delimiter(')string(Nat)delimiter(')operator(]) operator(=) integer(24)operator(;)
+local_variable($age)operator([)delimiter(')string(Jules)delimiter(')operator(]) operator(=) integer(25)operator(;)
+local_variable($age)operator([)delimiter(')string(Josh)delimiter(')operator(]) operator(=) integer(17)operator(;)
+
+local_variable($age) operator(=) ident(array_combine)operator(()pre_type(array)operator(()delimiter(')string(Nat)delimiter(')operator(,) delimiter(')string(Jules)delimiter(')operator(,) delimiter(')string(Josh)delimiter(')operator(\))operator(,) pre_type(array)operator(()integer(24)operator(,) integer(25)operator(,) integer(17)operator(\))operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($food_colour) operator(=) pre_type(array)operator(()delimiter(')string(Apple)delimiter(') operator(=>) delimiter(')string(red)delimiter(')operator(,) delimiter(')string(Banana)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,)
+ delimiter(')string(Lemon)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,) delimiter(')string(Carrot)delimiter(') operator(=>) delimiter(')string(orange)delimiter(')operator(\))operator(;)
+
+local_variable($food_colour)operator([)delimiter(')string(Apple)delimiter(')operator(]) operator(=) delimiter(')string(red)delimiter(')operator(;) local_variable($food_colour)operator([)delimiter(')string(Banana)delimiter(')operator(]) operator(=) delimiter(')string(yellow)delimiter(')operator(;)
+local_variable($food_colour)operator([)delimiter(')string(Lemon)delimiter(')operator(]) operator(=) delimiter(')string(yellow)delimiter(')operator(;) local_variable($food_colour)operator([)delimiter(')string(Carrot)delimiter(')operator(]) operator(=) delimiter(')string(orange)delimiter(')operator(;)
+
+local_variable($food_colour) operator(=) ident(array_combine)operator(()pre_type(array)operator(()delimiter(')string(Apple)delimiter(')operator(,) delimiter(')string(Banana)delimiter(')operator(,) delimiter(')string(Lemon)delimiter(')operator(,) delimiter(')string(Carrot)delimiter(')operator(\))operator(,)
+ pre_type(array)operator(()delimiter(')string(red)delimiter(')operator(,) delimiter(')string(yellow)delimiter(')operator(,) delimiter(')string(yellow)delimiter(')operator(,) delimiter(')string(orange)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// @@PLEAC@@_5.1)
+local_variable($hash)operator([)local_variable($key)operator(]) operator(=) local_variable($value)operator(;)
+
+comment(// ------------)
+
+local_variable($food_colour) operator(=) pre_type(array)operator(()delimiter(')string(Apple)delimiter(') operator(=>) delimiter(')string(red)delimiter(')operator(,) delimiter(')string(Banana)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,)
+ delimiter(')string(Lemon)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,) delimiter(')string(Carrot)delimiter(') operator(=>) delimiter(')string(orange)delimiter(')operator(\))operator(;)
+
+local_variable($food_colour)operator([)delimiter(')string(Raspberry)delimiter(')operator(]) operator(=) delimiter(')string(pink)delimiter(')operator(;)
+
+pre_type(echo) delimiter(")string(Known foods:)char(\\n)delimiter(")operator(;)
+reserved(foreach)operator(()local_variable($food_colour) reserved(as) local_variable($food) operator(=>) local_variable($colour)operator(\)) pre_type(echo) delimiter(")operator({)local_variable($food)operator(})char(\\n)delimiter(")operator(;)
+
+comment(// @@PLEAC@@_5.2)
+comment(// Returns TRUE on all existing entries with non-NULL values)
+reserved(if) operator(()pre_type(isset)operator(()local_variable($hash)operator([)local_variable($key)operator(])operator(\))operator(\))
+ operator(;) comment(// entry exists )
+reserved(else)
+ operator(;) comment(// no such entry )
+
+comment(// ------------)
+
+comment(// Returns TRUE on all existing entries regardless of attached value)
+reserved(if) operator(()ident(array_key_exists)operator(()local_variable($key)operator(,) local_variable($hash)operator(\))operator(\))
+ operator(;) comment(// entry exists )
+reserved(else)
+ operator(;) comment(// no such entry )
+
+comment(// ----------------------------)
+
+local_variable($food_colour) operator(=) pre_type(array)operator(()delimiter(')string(Apple)delimiter(') operator(=>) delimiter(')string(red)delimiter(')operator(,) delimiter(')string(Banana)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,)
+ delimiter(')string(Lemon)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,) delimiter(')string(Carrot)delimiter(') operator(=>) delimiter(')string(orange)delimiter(')operator(\))operator(;)
+
+reserved(foreach)operator(()pre_type(array)operator(()delimiter(')string(Banana)delimiter(')operator(,) delimiter(')string(Martini)delimiter(')operator(\)) reserved(as) local_variable($name)operator(\))
+operator({)
+ reserved(if) operator(()pre_type(isset)operator(()local_variable($food_colour)operator([)local_variable($name)operator(])operator(\))operator(\))
+ pre_type(echo) delimiter(")operator({)local_variable($name)operator(})string( is a food.)char(\\n)delimiter(")operator(;)
+ reserved(else)
+ pre_type(echo) delimiter(")operator({)local_variable($name)operator(})string( is a drink.)char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// ----------------------------)
+
+local_variable($age) operator(=) pre_type(array)operator(()delimiter(')string(Toddler)delimiter(') operator(=>) integer(3)operator(,) delimiter(')string(Unborn)delimiter(') operator(=>) integer(0)operator(,) delimiter(')string(Phantasm)delimiter(') operator(=>) constant(NULL)operator(\))operator(;)
+
+reserved(foreach)operator(()pre_type(array)operator(()delimiter(')string(Toddler)delimiter(')operator(,) delimiter(')string(Unborn)delimiter(')operator(,) delimiter(')string(Phantasm)delimiter(')operator(,) delimiter(')string(Relic)delimiter(')operator(\)) reserved(as) local_variable($thing)operator(\))
+operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($thing)operator(})string(:)delimiter(")operator(;)
+ reserved(if) operator(()ident(array_key_exists)operator(()local_variable($thing)operator(,) local_variable($age)operator(\))operator(\)) pre_type(echo) delimiter(')string( exists)delimiter(')operator(;)
+ reserved(if) operator(()pre_type(isset)operator(()local_variable($age)operator([)local_variable($thing)operator(])operator(\))operator(\)) pre_type(echo) delimiter(')string( non-NULL)delimiter(')operator(;)
+ reserved(if) operator(()local_variable($age)operator([)local_variable($thing)operator(])operator(\)) pre_type(echo) delimiter(')string( TRUE)delimiter(')operator(;)
+ pre_type(echo) delimiter(")char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// @@PLEAC@@_5.3)
+comment(// Remove one, or more, hash entries)
+pre_type(unset)operator(()local_variable($hash)operator([)local_variable($key)operator(])operator(\))operator(;)
+
+pre_type(unset)operator(()local_variable($hash)operator([)local_variable($key1)operator(])operator(,) local_variable($hash)operator([)local_variable($key2)operator(])operator(,) local_variable($hash)operator([)local_variable($key3)operator(])operator(\))operator(;)
+
+comment(// Remove entire hash)
+pre_type(unset)operator(()local_variable($hash)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(print_foods)operator(()operator(\))
+operator({)
+ comment(// Perl example uses a global variable)
+ pre_type(global) local_variable($food_colour)operator(;)
+
+ local_variable($foods) operator(=) ident(array_keys)operator(()local_variable($food_colour)operator(\))operator(;)
+
+ pre_type(echo) delimiter(')string(Foods:)delimiter(')operator(;)
+ reserved(foreach)operator(()local_variable($foods) reserved(as) local_variable($food)operator(\)) pre_type(echo) delimiter(")string( )operator({)local_variable($food)operator(})delimiter(")operator(;)
+
+ pre_type(echo) delimiter(")char(\\n)string(Values:)char(\\n)delimiter(")operator(;)
+ reserved(foreach)operator(()local_variable($foods) reserved(as) local_variable($food)operator(\))
+ operator({)
+ local_variable($colour) operator(=) local_variable($food_colour)operator([)local_variable($food)operator(])operator(;)
+
+ reserved(if) operator(()pre_type(isset)operator(()local_variable($colour)operator(\))operator(\))
+ pre_type(echo) delimiter(")string( )operator({)local_variable($colour)operator(})char(\\n)delimiter(")operator(;)
+ reserved(else)
+ pre_type(echo) delimiter(")string( nullified or removed)char(\\n)delimiter(")operator(;)
+ operator(})
+operator(})
+
+comment(// ------------)
+
+local_variable($food_colour) operator(=) pre_type(array)operator(()delimiter(')string(Apple)delimiter(') operator(=>) delimiter(')string(red)delimiter(')operator(,) delimiter(')string(Banana)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,)
+ delimiter(')string(Lemon)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,) delimiter(')string(Carrot)delimiter(') operator(=>) delimiter(')string(orange)delimiter(')operator(\))operator(;)
+
+pre_type(echo) delimiter(")string(Initially:)char(\\n)delimiter(")operator(;) ident(print_foods)operator(()operator(\))operator(;)
+
+comment(// Nullify an entry)
+local_variable($food_colour)operator([)delimiter(')string(Banana)delimiter(')operator(]) operator(=) constant(NULL)operator(;)
+pre_type(echo) delimiter(")char(\\n)string(With 'Banana' nullified)char(\\n)delimiter(")operator(;)
+ident(print_foods)operator(()operator(\))operator(;)
+
+comment(// Remove an entry)
+pre_type(unset)operator(()local_variable($food_colour)operator([)delimiter(')string(Banana)delimiter(')operator(])operator(\))operator(;)
+pre_type(echo) delimiter(")char(\\n)string(With 'Banana' removed)char(\\n)delimiter(")operator(;)
+ident(print_foods)operator(()operator(\))operator(;)
+
+comment(// Destroy the hash)
+pre_type(unset)operator(()local_variable($food_colour)operator(\))operator(;)
+
+comment(// @@PLEAC@@_5.4)
+comment(// Access keys and values)
+reserved(foreach)operator(()local_variable($hash) reserved(as) local_variable($key) operator(=>) local_variable($value)operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+comment(// Access keys only)
+reserved(foreach)operator(()ident(array_keys)operator(()local_variable($hash)operator(\)) reserved(as) local_variable($key)operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+comment(// Access values only)
+reserved(foreach)operator(()local_variable($hash) reserved(as) local_variable($value)operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+comment(// ----------------------------)
+
+local_variable($food_colour) operator(=) pre_type(array)operator(()delimiter(')string(Apple)delimiter(') operator(=>) delimiter(')string(red)delimiter(')operator(,) delimiter(')string(Banana)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,)
+ delimiter(')string(Lemon)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,) delimiter(')string(Carrot)delimiter(') operator(=>) delimiter(')string(orange)delimiter(')operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($food_colour) reserved(as) local_variable($food) operator(=>) local_variable($colour)operator(\))
+operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($food)operator(})string( is )operator({)local_variable($colour)operator(})char(\\n)delimiter(")operator(;)
+operator(})
+
+reserved(foreach)operator(()ident(array_keys)operator(()local_variable($food_colour)operator(\)) reserved(as) local_variable($food)operator(\))
+operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($food)operator(})string( is )operator({)local_variable($food_colour)operator([)local_variable($food)operator(])operator(})char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// ----------------------------)
+
+comment(// 'countfrom' - count number of messages from each sender)
+
+local_variable($line) operator(=) ident(fgets)operator(()constant(STDIN)operator(\))operator(;)
+
+reserved(while) operator(()operator(!)ident(feof)operator(()constant(STDIN)operator(\))operator(\))
+operator({)
+ reserved(if) operator(()ident(preg_match)operator(()delimiter(')string(/^From: (.*\)/)delimiter(')operator(,) local_variable($line)operator(,) local_variable($matches)operator(\))operator(\))
+ operator({)
+ reserved(if) operator(()pre_type(isset)operator(()local_variable($from)operator([)local_variable($matches)operator([)integer(1)operator(])operator(])operator(\))operator(\))
+ local_variable($from)operator([)local_variable($matches)operator([)integer(1)operator(])operator(]) operator(+)operator(=) integer(1)operator(;)
+ reserved(else)
+ local_variable($from)operator([)local_variable($matches)operator([)integer(1)operator(])operator(]) operator(=) integer(1)operator(;)
+ operator(})
+
+ local_variable($line) operator(=) ident(fgets)operator(()constant(STDIN)operator(\))operator(;)
+operator(})
+
+reserved(if) operator(()pre_type(isset)operator(()local_variable($from)operator(\))operator(\))
+operator({)
+ pre_type(echo) delimiter(")string(Senders:)char(\\n)delimiter(")operator(;)
+ reserved(foreach)operator(()local_variable($from) reserved(as) local_variable($sender) operator(=>) local_variable($count)operator(\)) pre_type(echo) delimiter(")operator({)local_variable($sender)operator(})string( : )operator({)local_variable($count)operator(})char(\\n)delimiter(")operator(;)
+operator(})
+reserved(else)
+operator({)
+ pre_type(echo) delimiter(")string(No valid data entered)char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// @@PLEAC@@_5.5)
+comment(// PHP offers, 'print_r', which prints hash contents in 'debug' form; it also)
+comment(// works recursively, printing any contained arrays in similar form)
+comment(// Array)
+comment(// ()
+comment(// [key1] => value1 )
+comment(// [key2] => value2)
+comment(// ...)
+comment(// \))
+
+ident(print_r)operator(()local_variable($hash)operator(\))operator(;)
+
+comment(// ------------)
+
+comment(// Based on Perl example; non-recursive, so contained arrays not printed correctly)
+reserved(foreach)operator(()local_variable($hash) reserved(as) local_variable($key) operator(=>) local_variable($value)operator(\))
+operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($key)operator(})string( => )local_variable($value)char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// ----------------------------)
+
+comment(// Sorted by keys)
+
+comment(// 1. Sort the original hash)
+ident(ksort)operator(()local_variable($hash)operator(\))operator(;)
+
+comment(// 2. Extract keys, sort, traverse original in key order)
+local_variable($keys) operator(=) ident(array_keys)operator(()local_variable($hash)operator(\))operator(;) ident(sort)operator(()local_variable($keys)operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($keys) reserved(as) local_variable($key)operator(\))
+operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($key)operator(})string( => )operator({)local_variable($hash)operator([)local_variable($key)operator(])operator(})char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// Sorted by values)
+
+comment(// 1. Sort the original hash)
+ident(asort)operator(()local_variable($hash)operator(\))operator(;)
+
+comment(// 2. Extract values, sort, traverse original in value order [warning: finds )
+comment(// only first matching key in the case where duplicate values exist])
+local_variable($values) operator(=) ident(array_values)operator(()local_variable($hash)operator(\))operator(;) ident(sort)operator(()local_variable($values)operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($values) reserved(as) local_variable($value)operator(\))
+operator({)
+ pre_type(echo) local_variable($value) operator(.) delimiter(')string( <= )delimiter(') operator(.) ident(array_search)operator(()local_variable($value)operator(,) local_variable($hash)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// @@PLEAC@@_5.6)
+comment(// Unless sorted, hash elements remain in the order of insertion. If care is taken to)
+comment(// always add a new element to the end of the hash, then element order is the order)
+comment(// of insertion. The following function, 'array_push_associative' [modified from original)
+comment(// found at 'array_push' section of PHP documentation], does just that)
+pre_type(function) ident(array_push_associative)operator(()operator(&)local_variable($arr)operator(\))
+operator({)
+ reserved(foreach) operator(()ident(func_get_args)operator(()operator(\)) reserved(as) local_variable($arg)operator(\))
+ operator({)
+ reserved(if) operator(()ident(is_array)operator(()local_variable($arg)operator(\))operator(\))
+ reserved(foreach) operator(()local_variable($arg) reserved(as) local_variable($key) operator(=>) local_variable($value)operator(\)) operator({) local_variable($arr)operator([)local_variable($key)operator(]) operator(=) local_variable($value)operator(;) local_variable($ret)operator(++)operator(;) operator(})
+ reserved(else)
+ local_variable($arr)operator([)local_variable($arg)operator(]) operator(=) delimiter(')delimiter(')operator(;)
+ operator(})
+
+ reserved(return) local_variable($ret)operator(;)
+operator(})
+
+comment(// ------------)
+
+local_variable($food_colour) operator(=) pre_type(array)operator(()operator(\))operator(;)
+
+comment(// Individual calls, or ...)
+ident(array_push_associative)operator(()local_variable($food_colour)operator(,) pre_type(array)operator(()delimiter(')string(Banana)delimiter(') operator(=>) delimiter(')string(Yellow)delimiter(')operator(\))operator(\))operator(;)
+ident(array_push_associative)operator(()local_variable($food_colour)operator(,) pre_type(array)operator(()delimiter(')string(Apple)delimiter(') operator(=>) delimiter(')string(Green)delimiter(')operator(\))operator(\))operator(;)
+ident(array_push_associative)operator(()local_variable($food_colour)operator(,) pre_type(array)operator(()delimiter(')string(Lemon)delimiter(') operator(=>) delimiter(')string(Yellow)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// ... one call, one array; physical order retained)
+comment(// array_push_associative($food_colour, array('Banana' => 'Yellow', 'Apple' => 'Green', 'Lemon' => 'Yellow'\)\);)
+
+ident(print_r)operator(()local_variable($food_colour)operator(\))operator(;)
+
+pre_type(echo) delimiter(")char(\\n)string(In insertion order:)char(\\n)delimiter(")operator(;)
+reserved(foreach)operator(()local_variable($food_colour) reserved(as) local_variable($food) operator(=>) local_variable($colour)operator(\)) pre_type(echo) delimiter(")string( )operator({)local_variable($food)operator(})string( => )operator({)local_variable($colour)operator(})char(\\n)delimiter(")operator(;)
+
+local_variable($foods) operator(=) ident(array_keys)operator(()local_variable($food_colour)operator(\))operator(;)
+
+pre_type(echo) delimiter(")char(\\n)string(Still in insertion order:)char(\\n)delimiter(")operator(;)
+reserved(foreach)operator(()local_variable($foods) reserved(as) local_variable($food)operator(\)) pre_type(echo) delimiter(")string( )operator({)local_variable($food)operator(})string( => )operator({)local_variable($food_colour)operator([)local_variable($food)operator(])operator(})char(\\n)delimiter(")operator(;)
+
+comment(// @@PLEAC@@_5.7)
+reserved(foreach)operator(()ident(array_slice)operator(()ident(preg_split)operator(()delimiter(')string(/)string(\\)string(n/)delimiter(')operator(,) error(`)ident(who)error(`)operator(\))operator(,) integer(0)operator(,) integer(-1)operator(\)) reserved(as) local_variable($entry)operator(\))
+operator({)
+ pre_type(list)operator(()local_variable($user)operator(,) local_variable($tty)operator(\)) operator(=) ident(preg_split)operator(()delimiter(')string(/)string(\\)string(s/)delimiter(')operator(,) local_variable($entry)operator(\))operator(;)
+ local_variable($ttys)operator([)local_variable($user)operator(])operator([)operator(]) operator(=) local_variable($tty)operator(;)
+
+ comment(// Could instead do this:)
+ comment(// $user = array_slice(preg_split('/\\s/', $entry\), 0, 2\);)
+ comment(// $ttys[$user[0]][] = $user[1];)
+operator(})
+
+ident(ksort)operator(()local_variable($ttys)operator(\))operator(;)
+
+comment(// ------------)
+
+reserved(foreach)operator(()local_variable($ttys) reserved(as) local_variable($user) operator(=>) local_variable($all_ttys)operator(\))
+operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($user)operator(})string(: )delimiter(") operator(.) ident(join)operator(()delimiter(')string( )delimiter(')operator(,) local_variable($all_ttys)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// ------------)
+
+reserved(foreach)operator(()local_variable($ttys) reserved(as) local_variable($user) operator(=>) local_variable($all_ttys)operator(\))
+operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($user)operator(})string(: )delimiter(") operator(.) ident(join)operator(()delimiter(')string( )delimiter(')operator(,) local_variable($all_ttys)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+ reserved(foreach)operator(()local_variable($all_ttys) reserved(as) local_variable($tty)operator(\))
+ operator({)
+ local_variable($stat) operator(=) ident(stat)operator(()delimiter(')string(/dev/$tty)delimiter(')operator(\))operator(;)
+ local_variable($pwent) operator(=) ident(posix_getpwuid)operator(()local_variable($stat)operator([)delimiter(')string(uid)delimiter(')operator(])operator(\))operator(;)
+ local_variable($user) operator(=) pre_type(isset)operator(()local_variable($pwent)operator([)delimiter(')string(name)delimiter(')operator(])operator(\)) operator(?) local_variable($pwent)operator([)delimiter(')string(name)delimiter(')operator(]) operator(:) delimiter(')string(Not available)delimiter(')operator(;)
+ pre_type(echo) delimiter(")operator({)local_variable($tty)operator(})string( owned by: )operator({)local_variable($user)operator(})char(\\n)delimiter(")operator(;)
+ operator(})
+operator(})
+
+comment(// @@PLEAC@@_5.8)
+comment(// PHP offers the 'array_flip' function to perform the task of exchanging the keys / values)
+comment(// of a hash i.e. invert or 'flip' a hash)
+
+local_variable($reverse) operator(=) ident(array_flip)operator(()local_variable($hash)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+local_variable($surname) operator(=) pre_type(array)operator(()delimiter(')string(Babe)delimiter(') operator(=>) delimiter(')string(Ruth)delimiter(')operator(,) delimiter(')string(Mickey)delimiter(') operator(=>) delimiter(')string(Mantle)delimiter(')operator(\))operator(;)
+local_variable($first_name) operator(=) ident(array_flip)operator(()local_variable($surname)operator(\))operator(;)
+
+pre_type(echo) delimiter(")operator({)local_variable($first_name)operator([)delimiter(')string(Mantle)delimiter(')operator(])operator(})char(\\n)delimiter(")operator(;)
+
+comment(// ----------------------------)
+
+local_variable($argc) operator(==) integer(2) operator(|)operator(|) reserved(die)operator(()delimiter(")string(usage: )operator({)local_variable($argv)operator([)integer(0)operator(])operator(})string( food|colour)char(\\n)delimiter(")operator(\))operator(;)
+
+local_variable($given) operator(=) local_variable($argv)operator([)integer(1)operator(])operator(;)
+
+local_variable($colour) operator(=) pre_type(array)operator(()delimiter(')string(Apple)delimiter(') operator(=>) delimiter(')string(red)delimiter(')operator(,) delimiter(')string(Banana)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,)
+ delimiter(')string(Lemon)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,) delimiter(')string(Carrot)delimiter(') operator(=>) delimiter(')string(orange)delimiter(')operator(\))operator(;)
+
+local_variable($food) operator(=) ident(array_flip)operator(()local_variable($colour)operator(\))operator(;)
+
+reserved(if) operator(()pre_type(isset)operator(()local_variable($colour)operator([)local_variable($given)operator(])operator(\))operator(\))
+ pre_type(echo) delimiter(")operator({)local_variable($given)operator(})string( is a food with colour: )operator({)local_variable($colour)operator([)local_variable($given)operator(])operator(})char(\\n)delimiter(")operator(;)
+
+reserved(if) operator(()pre_type(isset)operator(()local_variable($food)operator([)local_variable($given)operator(])operator(\))operator(\))
+ pre_type(echo) delimiter(")operator({)local_variable($food)operator([)local_variable($given)operator(])operator(})string( is a food with colour: )operator({)local_variable($given)operator(})char(\\n)delimiter(")operator(;)
+
+comment(// ----------------------------)
+
+local_variable($food_colour) operator(=) pre_type(array)operator(()delimiter(')string(Apple)delimiter(') operator(=>) delimiter(')string(red)delimiter(')operator(,) delimiter(')string(Banana)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,)
+ delimiter(')string(Lemon)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,) delimiter(')string(Carrot)delimiter(') operator(=>) delimiter(')string(orange)delimiter(')operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($food_colour) reserved(as) local_variable($food) operator(=>) local_variable($colour)operator(\))
+operator({)
+ local_variable($foods_with_colour)operator([)local_variable($colour)operator(])operator([)operator(]) operator(=) local_variable($food)operator(;)
+operator(})
+
+local_variable($colour) operator(=) delimiter(')string(yellow)delimiter(')operator(;)
+pre_type(echo) delimiter(")string(foods with colour )operator({)local_variable($colour)operator(})string( were: )delimiter(") operator(.) ident(join)operator(()delimiter(')string( )delimiter(')operator(,) local_variable($foods_with_colour)operator([)local_variable($colour)operator(])operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// @@PLEAC@@_5.9)
+comment(// PHP implements a swag of sorting functions, most designed to work with numerically-indexed)
+comment(// arrays. For sorting hashes, the 'key' sorting functions are required:)
+comment(// * 'ksort', 'krsort', 'uksort')
+
+comment(// Ascending order)
+ident(ksort)operator(()local_variable($hash)operator(\))operator(;)
+
+comment(// Descending order [i.e. reverse sort])
+ident(krsort)operator(()local_variable($hash)operator(\))operator(;)
+
+comment(// Comparator-based sort)
+
+pre_type(function) ident(comparator)operator(()local_variable($left)operator(,) local_variable($right)operator(\))
+operator({)
+ comment(// Compare left key with right key)
+ reserved(return) local_variable($left) operator(>) local_variable($right)operator(;)
+operator(})
+
+ident(uksort)operator(()local_variable($hash)operator(,) delimiter(')string(comparator)delimiter(')operator(\))operator(;)
+
+comment(// ----------------------------)
+
+local_variable($food_colour) operator(=) pre_type(array)operator(()delimiter(')string(Apple)delimiter(') operator(=>) delimiter(')string(red)delimiter(')operator(,) delimiter(')string(Banana)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,)
+ delimiter(')string(Lemon)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,) delimiter(')string(Carrot)delimiter(') operator(=>) delimiter(')string(orange)delimiter(')operator(\))operator(;)
+
+comment(// ------------)
+
+ident(ksort)operator(()local_variable($food_colour)operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($food_colour) reserved(as) local_variable($food) operator(=>) local_variable($colour)operator(\))
+operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($food)operator(})string( is )operator({)local_variable($colour)operator(})char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// ------------)
+
+ident(uksort)operator(()local_variable($food_colour)operator(,) ident(create_function)operator(()delimiter(')string($left, $right)delimiter(')operator(,) delimiter(')string(return $left > $right;)delimiter(')operator(\))operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($food_colour) reserved(as) local_variable($food) operator(=>) local_variable($colour)operator(\))
+operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($food)operator(})string( is )operator({)local_variable($colour)operator(})char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// @@PLEAC@@_5.10)
+comment(// PHP offers the 'array_merge' function for this task [a related function, 'array_combine',)
+comment(// may be used to create a hash from an array of keys, and one of values, respectively])
+
+comment(// Merge two, or more, arrays)
+local_variable($merged) operator(=) ident(array_merge)operator(()local_variable($a)operator(,) local_variable($b)operator(,) local_variable($c)operator(\))operator(;)
+
+comment(// Create a hash from array of keys, and of values, respectively)
+local_variable($hash) operator(=) ident(array_combine)operator(()local_variable($keys)operator(,) local_variable($values)operator(\))operator(;)
+
+comment(// ------------)
+
+comment(// Can always merge arrays manually )
+reserved(foreach)operator(()pre_type(array)operator(()local_variable($h1)operator(,) local_variable($h2)operator(,) local_variable($h3)operator(\)) reserved(as) local_variable($hash)operator(\))
+operator({)
+ reserved(foreach)operator(()local_variable($hash) reserved(as) local_variable($key) operator(=>) local_variable($value)operator(\))
+ operator({)
+ comment(// If same-key values differ, only latest retained)
+ local_variable($merged)operator([)local_variable($key)operator(]) operator(=) local_variable($value)operator(;)
+
+ comment(// Do this to append values for that key)
+ comment(// $merged[$key][] = $value;)
+ operator(})
+operator(})
+
+comment(// ----------------------------)
+
+local_variable($food_colour) operator(=) pre_type(array)operator(()delimiter(')string(Apple)delimiter(') operator(=>) delimiter(')string(red)delimiter(')operator(,) delimiter(')string(Banana)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,)
+ delimiter(')string(Lemon)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,) delimiter(')string(Carrot)delimiter(') operator(=>) delimiter(')string(orange)delimiter(')operator(\))operator(;)
+
+local_variable($drink_colour) operator(=) pre_type(array)operator(()delimiter(')string(Galliano)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,) delimiter(')string(Mai Tai)delimiter(') operator(=>) delimiter(')string(blue)delimiter(')operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($ingested_colour) operator(=) ident(array_merge)operator(()local_variable($food_colour)operator(,) local_variable($drink_colour)operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($substance_colour) operator(=) pre_type(array)operator(()operator(\))operator(;)
+
+reserved(foreach)operator(()pre_type(array)operator(()local_variable($food_colour)operator(,) local_variable($drink_colour)operator(\)) reserved(as) local_variable($hash)operator(\))
+operator({)
+ reserved(foreach)operator(()local_variable($hash) reserved(as) local_variable($substance) operator(=>) local_variable($colour)operator(\))
+ operator({)
+ reserved(if) operator(()ident(array_key_exists)operator(()local_variable($substance)operator(,) local_variable($substance_colour)operator(\))operator(\))
+ operator({)
+ pre_type(echo) delimiter(")string(Warning )operator({)local_variable($substance_colour)operator([)local_variable($substance)operator(])operator(})string( seen twice. Using first definition.)char(\\n)delimiter(")operator(;)
+ reserved(continue)operator(;)
+ operator(})
+ local_variable($substance_colour)operator([)local_variable($substance)operator(]) operator(=) local_variable($colour)operator(;)
+ operator(})
+operator(})
+
+comment(// @@PLEAC@@_5.11)
+comment(// PHP offers a number of array-based 'set operation' functions:)
+comment(// * union: array_merge)
+comment(// * intersection: array_intersect and family)
+comment(// * difference: array_diff and family)
+comment(// which may be used for this type of task)
+
+comment(// Keys occurring in both hashes)
+local_variable($common) operator(=) ident(array_intersect_key)operator(()local_variable($h1)operator(,) local_variable($h2)operator(\))operator(;)
+
+comment(// Keys occurring in the first hash [left side], but not in the second hash)
+local_variable($this_not_that) operator(=) ident(array_diff_key)operator(()local_variable($h1)operator(,) local_variable($h2)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+local_variable($food_colour) operator(=) pre_type(array)operator(()delimiter(')string(Apple)delimiter(') operator(=>) delimiter(')string(red)delimiter(')operator(,) delimiter(')string(Banana)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,)
+ delimiter(')string(Lemon)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,) delimiter(')string(Carrot)delimiter(') operator(=>) delimiter(')string(orange)delimiter(')operator(\))operator(;)
+
+local_variable($citrus_colour) operator(=) pre_type(array)operator(()delimiter(')string(Lemon)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,) delimiter(')string(Orange)delimiter(') operator(=>) delimiter(')string(orange)delimiter(')operator(,) delimiter(')string(Lime)delimiter(') operator(=>) delimiter(')string(green)delimiter(')operator(\))operator(;)
+
+local_variable($non_citrus) operator(=) ident(array_diff_key)operator(()local_variable($food_colour)operator(,) local_variable($citrus_colour)operator(\))operator(;)
+
+comment(// @@PLEAC@@_5.12)
+comment(// PHP implements a special type known as a 'resource' that encompasses things like file handles,)
+comment(// sockets, database connections, and many others. The 'resource' type is, essentially, a)
+comment(// reference variable that is not readily serialisable. That is to say:)
+comment(// * A 'resource' may be converted to a string representation via the 'var_export' function)
+comment(// * That same string cannot be converted back into a 'resource')
+comment(// So, in terms of array handling, 'resource' types may be stored as array reference values,)
+comment(// but cannot be used as keys. )
+comment(//)
+comment(// I suspect it is this type of problem that the Perl::Tie package helps resolve. However, since)
+comment(// PHP doesn't, AFAIK, sport a similar facility, the examples in this section cannot be)
+comment(// implemented using file handles as keys)
+
+local_variable($filenames) operator(=) pre_type(array)operator(()delimiter(')string(/etc/termcap)delimiter(')operator(,) delimiter(')string(/vmlinux)delimiter(')operator(,) delimiter(')string(/bin/cat)delimiter(')operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($filenames) reserved(as) local_variable($filename)operator(\))
+operator({)
+ reserved(if) operator(()operator(!)operator(()local_variable($fh) operator(=) ident(fopen)operator(()local_variable($filename)operator(,) delimiter(')string(r)delimiter(')operator(\))operator(\))operator(\)) reserved(continue)operator(;)
+
+ comment(// Cannot do this as required by the Perl code:)
+ comment(// $name[$fh] = $filename;)
+
+ comment(// Ok)
+ local_variable($name)operator([)local_variable($filename)operator(]) operator(=) local_variable($fh)operator(;)
+operator(})
+
+comment(// Would traverse array via:)
+comment(//)
+comment(// foreach(array_keys($name\) as $fh\))
+comment(// ...)
+comment(// or)
+comment(//)
+comment(// foreach($name as $fh => $filename\))
+comment(// ...)
+comment(// but since '$fh' cannot be a key, either of these will work:)
+comment(//)
+comment(// foreach($name as $filename => $fh\))
+comment(// or)
+reserved(foreach)operator(()ident(array_values)operator(()local_variable($name)operator(\)) reserved(as) local_variable($fh)operator(\))
+operator({)
+ ident(fclose)operator(()local_variable($fh)operator(\))operator(;)
+operator(})
+
+comment(// @@PLEAC@@_5.13)
+comment(// PHP hashes are dynamic expanding and contracting as entries are added, and removed,)
+comment(// respectively. Thus, there is no need to presize a hash, nor is there, AFAIK, any)
+comment(// means of doing so except by the number of datums used when defining the hash)
+
+comment(// zero elements)
+local_variable($hash) operator(=) pre_type(array)operator(()operator(\))operator(;)
+
+comment(// ------------)
+
+comment(// three elements)
+local_variable($hash) operator(=) pre_type(array)operator(()delimiter(')string(Apple)delimiter(') operator(=>) delimiter(')string(red)delimiter(')operator(,) delimiter(')string(Lemon)delimiter(') operator(=>) delimiter(')string(yellow)delimiter(')operator(,) delimiter(')string(Carrot)delimiter(') operator(=>) delimiter(')string(orange)delimiter(')operator(\))operator(;)
+
+comment(// @@PLEAC@@_5.14)
+reserved(foreach)operator(()local_variable($array) reserved(as) local_variable($element)operator(\)) local_variable($count)operator([)local_variable($element)operator(]) operator(+)operator(=) integer(1)operator(;)
+
+comment(// @@PLEAC@@_5.15)
+local_variable($father) operator(=) pre_type(array)operator(()delimiter(')string(Cain)delimiter(') operator(=>) delimiter(')string(Adam)delimiter(')operator(,) delimiter(')string(Abel)delimiter(') operator(=>) delimiter(')string(Adam)delimiter(')operator(,) delimiter(')string(Seth)delimiter(') operator(=>) delimiter(')string(Adam)delimiter(')operator(,) delimiter(')string(Enoch)delimiter(') operator(=>) delimiter(')string(Cain)delimiter(')operator(,)
+ delimiter(')string(Irad)delimiter(') operator(=>) delimiter(')string(Enoch)delimiter(')operator(,) delimiter(')string(Mehujael)delimiter(') operator(=>) delimiter(')string(Irad)delimiter(')operator(,) delimiter(')string(Methusael)delimiter(')operator(=>) delimiter(')string(Mehujael)delimiter(')operator(,)
+ delimiter(')string(Lamech)delimiter(') operator(=>) delimiter(')string(Methusael)delimiter(')operator(,) delimiter(')string(Jabal)delimiter(') operator(=>) delimiter(')string(Lamech)delimiter(')operator(,) delimiter(')string(Jubal)delimiter(') operator(=>) delimiter(')string(Lamech)delimiter(')operator(,)
+ delimiter(')string(Tubalcain)delimiter(') operator(=>) delimiter(')string(Lamech)delimiter(')operator(,) delimiter(')string(Enos)delimiter(') operator(=>) delimiter(')string(Seth)delimiter(')operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($name) operator(=) ident(trim)operator(()ident(fgets)operator(()constant(STDIN)operator(\))operator(\))operator(;)
+
+reserved(while) operator(()operator(!)ident(feof)operator(()constant(STDIN)operator(\))operator(\))
+operator({)
+ reserved(while) operator(()constant(TRUE)operator(\))
+ operator({)
+ pre_type(echo) delimiter(")local_variable($name)char(\\n)delimiter(")operator(;)
+
+ comment(// Can use either:)
+ reserved(if) operator(()operator(!)pre_type(isset)operator(()local_variable($father)operator([)local_variable($name)operator(])operator(\))operator(\)) reserved(break)operator(;)
+ local_variable($name) operator(=) local_variable($father)operator([)local_variable($name)operator(])operator(;)
+
+ comment(// or:)
+ comment(// if (!key_exists($name, $father\)\) break;)
+ comment(// $name = $father[$name];)
+
+ comment(// or combine the two lines:)
+ comment(// if (!($name = $father[$name]\)\) break;)
+ operator(})
+
+ pre_type(echo) delimiter(")char(\\n)delimiter(")operator(;)
+ local_variable($name) operator(=) ident(trim)operator(()ident(fgets)operator(()constant(STDIN)operator(\))operator(\))operator(;)
+operator(})
+
+comment(// ----------------------------)
+
+ident(define)operator(()constant(SEP)operator(,) delimiter(')string( )delimiter(')operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($father) reserved(as) local_variable($child) operator(=>) local_variable($parent)operator(\))
+operator({)
+ reserved(if) operator(()operator(!)local_variable($children)operator([)local_variable($parent)operator(])operator(\))
+ local_variable($children)operator([)local_variable($parent)operator(]) operator(=) local_variable($child)operator(;)
+ reserved(else)
+ local_variable($children)operator([)local_variable($parent)operator(]) operator(.)operator(=) constant(SEP) operator(.) local_variable($child)operator(;)
+operator(})
+
+local_variable($name) operator(=) ident(trim)operator(()ident(fgets)operator(()constant(STDIN)operator(\))operator(\))operator(;)
+
+reserved(while) operator(()operator(!)ident(feof)operator(()constant(STDIN)operator(\))operator(\))
+operator({)
+ pre_type(echo) local_variable($name) operator(.) delimiter(')string( begat )delimiter(')operator(;)
+
+ reserved(if) operator(()operator(!)local_variable($children)operator([)local_variable($name)operator(])operator(\))
+ pre_type(echo) delimiter(")string(Nothing)char(\\n)delimiter(")
+ reserved(else)
+ pre_type(echo) ident(str_replace)operator(()constant(SEP)operator(,) delimiter(')string(, )delimiter(')operator(,) local_variable($children)operator([)local_variable($name)operator(])operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+ local_variable($name) operator(=) ident(trim)operator(()ident(fgets)operator(()constant(STDIN)operator(\))operator(\))operator(;)
+operator(})
+
+comment(// ----------------------------)
+
+ident(define)operator(()constant(SEP)operator(,) delimiter(')string( )delimiter(')operator(\))operator(;)
+
+local_variable($files) operator(=) pre_type(array)operator(()delimiter(')string(/tmp/a)delimiter(')operator(,) delimiter(')string(/tmp/b)delimiter(')operator(,) delimiter(')string(/tmp/c)delimiter(')operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($files) reserved(as) local_variable($file)operator(\))
+operator({)
+ reserved(if) operator(()operator(!)ident(is_file)operator(()local_variable($file)operator(\))operator(\)) operator({) pre_type(echo) delimiter(")string(Skipping )operator({)local_variable($file)operator(})char(\\n)delimiter(")operator(;) reserved(continue)operator(;) operator(})
+ reserved(if) operator(()operator(!)operator(()local_variable($fh) operator(=) ident(fopen)operator(()local_variable($file)operator(,) delimiter(')string(r)delimiter(')operator(\))operator(\))operator(\)) operator({) pre_type(echo) delimiter(")string(Skipping )operator({)local_variable($file)operator(})char(\\n)delimiter(")operator(;) reserved(continue)operator(;) operator(})
+
+ local_variable($line) operator(=) ident(fgets)operator(()local_variable($fh)operator(\))operator(;)
+
+ reserved(while) operator(()operator(!)ident(feof)operator(()local_variable($fh)operator(\))operator(\))
+ operator({)
+ reserved(if) operator(()ident(preg_match)operator(()delimiter(')string(/^)string(\\)string(s*#)string(\\)string(s*include)string(\\)string(s*<([^>]+\)>/)delimiter(')operator(,) local_variable($line)operator(,) local_variable($matches)operator(\))operator(\))
+ operator({)
+ reserved(if) operator(()pre_type(isset)operator(()local_variable($includes)operator([)local_variable($matches)operator([)integer(1)operator(])operator(])operator(\))operator(\))
+ local_variable($includes)operator([)local_variable($matches)operator([)integer(1)operator(])operator(]) operator(.)operator(=) constant(SEP) operator(.) local_variable($file)operator(;)
+ reserved(else)
+ local_variable($includes)operator([)local_variable($matches)operator([)integer(1)operator(])operator(]) operator(=) local_variable($file)operator(;)
+ operator(})
+
+ local_variable($line) operator(=) ident(fgets)operator(()local_variable($fh)operator(\))operator(;)
+ operator(})
+
+ ident(fclose)operator(()local_variable($fh)operator(\))operator(;)
+operator(})
+
+ident(print_r)operator(()local_variable($includes)operator(\))operator(;)
+
+comment(// @@PLEAC@@_5.16)
+comment(// @@INCOMPLETE@@)
+comment(// @@INCOMPLETE@@)
+
+comment(// @@PLEAC@@_9.0)
+local_variable($entry) operator(=) ident(stat)operator(()delimiter(')string(/bin/vi)delimiter(')operator(\))operator(;)
+local_variable($entry) operator(=) ident(stat)operator(()delimiter(')string(/usr/bin)delimiter(')operator(\))operator(;)
+local_variable($entry) operator(=) ident(stat)operator(()local_variable($argv)operator([)integer(1)operator(])operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($entry) operator(=) ident(stat)operator(()delimiter(')string(/bin/vi)delimiter(')operator(\))operator(;)
+
+local_variable($ctime) operator(=) local_variable($entry)operator([)delimiter(')string(ctime)delimiter(')operator(])operator(;)
+local_variable($size) operator(=) local_variable($entry)operator([)delimiter(')string(size)delimiter(')operator(])operator(;)
+
+comment(// ----------------------------)
+
+comment(// For the simple task of determining whether a file contains, text', a simple)
+comment(// function that searches for a newline could be implemented. Not exactly)
+comment(// foolproof, but very simple, low overhead, no installation headaches ...)
+pre_type(function) ident(containsText)operator(()local_variable($file)operator(\))
+operator({)
+ local_variable($status) operator(=) constant(FALSE)operator(;)
+
+ reserved(if) operator(()operator(()local_variable($fp) operator(=) ident(fopen)operator(()local_variable($file)operator(,) delimiter(')string(r)delimiter(')operator(\))operator(\))operator(\))
+ operator({)
+ reserved(while) operator(()constant(FALSE) operator(!==) operator(()local_variable($char) operator(=) ident(fgetc)operator(()local_variable($fp)operator(\))operator(\))operator(\))
+ operator({)
+ reserved(if) operator(()local_variable($char) operator(==) delimiter(")char(\\n)delimiter(")operator(\)) operator({) local_variable($status) operator(=) constant(TRUE)operator(;) reserved(break)operator(;) operator(})
+ operator(})
+
+ ident(fclose)operator(()local_variable($fp)operator(\))operator(;)
+ operator(})
+
+ reserved(return) local_variable($status)operator(;)
+operator(})
+
+comment(// PHP offers the [currently experimental] Fileinfo group of functions to)
+comment(// determine file types based on their contents / 'magic numbers'. This)
+comment(// is functionality similar to the *NIX, 'file' utility. Note that it must)
+comment(// first be installed using the PEAR utility [see PHP documentation] )
+pre_type(function) ident(isTextFile)operator(()local_variable($file)operator(\))
+operator({)
+ comment(// Note: untested code, but I believe this is how it is supposed to work)
+ local_variable($finfo) operator(=) ident(finfo_open)operator(()constant(FILEINFO_NONE)operator(\))operator(;)
+ local_variable($status) operator(=) operator(()ident(finfo_file)operator(()local_variable($finfo)operator(,) local_variable($file)operator(\)) operator(==) delimiter(')string(ASCII text)delimiter(')operator(\))operator(;)
+ ident(finfo_close)operator(()local_variable($finfo)operator(\))operator(;)
+ reserved(return) local_variable($status)operator(;)
+operator(})
+
+comment(// Alternatively, use the *NIX utility, 'file', directly)
+pre_type(function) ident(isTextFile)operator(()local_variable($file)operator(\))
+operator({)
+ reserved(return) ident(exec)operator(()ident(trim)operator(()delimiter(')string(file -bN )delimiter(') operator(.) ident(escapeshellarg)operator(()local_variable($file)operator(\))operator(\))operator(\)) operator(==) delimiter(')string(ASCII text)delimiter(')operator(;)
+operator(})
+
+comment(// ----)
+
+ident(containsText)operator(()local_variable($argv)operator([)integer(1)operator(])operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(File )operator({)local_variable($argv)operator([)integer(1)operator(])operator(})string( doesn't have any text in it)char(\\n)delimiter(")operator(\))operator(;)
+
+ident(isTextFile)operator(()local_variable($argv)operator([)integer(1)operator(])operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(File )operator({)local_variable($argv)operator([)integer(1)operator(])operator(})string( doesn't have any text in it)char(\\n)delimiter(")operator(\))operator(;)
+
+comment(// ----------------------------)
+
+local_variable($dirname) operator(=) delimiter(')string(/usr/bin/)delimiter(')operator(;)
+
+operator(()local_variable($dirhdl) operator(=) ident(opendir)operator(()local_variable($dirname)operator(\))operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(Couldn't open )operator({)local_variable($dirname)operator(})char(\\n)delimiter(")operator(\))operator(;)
+
+reserved(while) operator(()operator(()local_variable($file) operator(=) ident(readdir)operator(()local_variable($dirhdl)operator(\))operator(\)) operator(!==) constant(FALSE)operator(\))
+operator({)
+ ident(printf)operator(()delimiter(")string(Inside %s is something called: %s)char(\\n)delimiter(")operator(,) local_variable($dirname)operator(,) local_variable($file)operator(\))operator(;)
+operator(})
+
+ident(closedir)operator(()local_variable($dirhdl)operator(\))operator(;)
+
+comment(// @@PLEAC@@_9.1)
+local_variable($filename) operator(=) delimiter(')string(example.txt)delimiter(')operator(;)
+
+comment(// Get the file's current access and modification time, respectively)
+local_variable($fs) operator(=) ident(stat)operator(()local_variable($filename)operator(\))operator(;)
+
+local_variable($readtime) operator(=) local_variable($fs)operator([)delimiter(')string(atime)delimiter(')operator(])operator(;)
+local_variable($writetime) operator(=) local_variable($fs)operator([)delimiter(')string(mtime)delimiter(')operator(])operator(;)
+
+comment(// Alter $writetime, and $readtime ...)
+
+comment(// Update file timestamp)
+ident(touch)operator(()local_variable($filename)operator(,) local_variable($writetime)operator(,) local_variable($readtime)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+local_variable($filename) operator(=) delimiter(')string(example.txt)delimiter(')operator(;)
+
+comment(// Get the file's current access and modification time, respectively)
+local_variable($fs) operator(=) ident(stat)operator(()local_variable($filename)operator(\))operator(;)
+
+local_variable($atime) operator(=) local_variable($fs)operator([)delimiter(')string(atime)delimiter(')operator(])operator(;)
+local_variable($mtime) operator(=) local_variable($fs)operator([)delimiter(')string(mtime)delimiter(')operator(])operator(;)
+
+comment(// Dedicated functions also exist to retrieve this information:)
+comment(//)
+comment(// $atime = $fileatime($filename\);)
+comment(// $mtime = $filemtime($filename\);)
+comment(//)
+
+comment(// Perform date arithmetic. Traditional approach where arithmetic is performed)
+comment(// directly with Epoch Seconds [i.e. the *NIX time stamp value] will work ...)
+
+ident(define)operator(()delimiter(')string(SECONDS_PER_DAY)delimiter(')operator(,) integer(60) operator(*) integer(60) operator(*) integer(24)operator(\))operator(;)
+
+comment(// Set file's access and modification times to 1 week ago)
+local_variable($atime) operator(-)operator(=) integer(7) operator(*) constant(SECONDS_PER_DAY)operator(;)
+local_variable($mtime) operator(-)operator(=) integer(7) operator(*) constant(SECONDS_PER_DAY)operator(;)
+
+comment(// ... but care must be taken to account for daylight saving. Therefore, the)
+comment(// recommended approach is to use library functions to perform such tasks:)
+
+local_variable($atime) operator(=) ident(strtotime)operator(()delimiter(')string(-7 days)delimiter(')operator(,) local_variable($atime)operator(\))operator(;)
+local_variable($mtime) operator(=) ident(strtotime)operator(()delimiter(')string(-7 days)delimiter(')operator(,) local_variable($mtime)operator(\))operator(;)
+
+comment(// Update file timestamp)
+ident(touch)operator(()local_variable($filename)operator(,) local_variable($mtime)operator(,) local_variable($atime)operator(\))operator(;)
+
+comment(// Good idea to clear the cache after such updates have occurred so fresh)
+comment(// values will be retrieved on next access)
+ident(clearstatcache)operator(()operator(\))operator(;)
+
+comment(// ----------------------------)
+
+local_variable($argc) operator(==) integer(2) operator(|)operator(|) reserved(die)operator(()delimiter(")string(usage: )operator({)local_variable($argv)operator([)integer(0)operator(])operator(})string( filename)char(\\n)delimiter(")operator(\))operator(;)
+
+local_variable($filename) operator(=) local_variable($argv)operator([)integer(1)operator(])operator(;)
+local_variable($fs) operator(=) ident(stat)operator(()local_variable($filename)operator(\))operator(;)
+
+local_variable($atime) operator(=) local_variable($fs)operator([)delimiter(')string(atime)delimiter(')operator(])operator(;)
+local_variable($mtime) operator(=) local_variable($fs)operator([)delimiter(')string(mtime)delimiter(')operator(])operator(;)
+
+comment(// Careful here: since interactive, use, 'system', not 'exec', to launch [latter)
+comment(// does not work under *NIX - at least, not for me :\)])
+ident(system)operator(()ident(trim)operator(()ident(getenv)operator(()delimiter(')string(EDITOR)delimiter(')operator(\)) operator(.) delimiter(')string( vi )delimiter(') operator(.) ident(escapeshellarg)operator(()local_variable($filename)operator(\))operator(\))operator(,) local_variable($retcode)operator(\))operator(;)
+
+ident(touch)operator(()local_variable($filename)operator(,) local_variable($mtime)operator(,) local_variable($atime)operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(Error updating timestamp on file, )operator({)local_variable($filename)operator(})string(!)char(\\n)delimiter(")operator(\))operator(;)
+
+comment(// @@PLEAC@@_9.2)
+comment(// The 'unlink' function is used to delete regular files, whilst the 'rmdir' function)
+comment(// does the same on non-empty directories. AFAIK, no recursive-deletion facility)
+comment(// exists, and must be manually programmed)
+
+local_variable($filename) operator(=) delimiter(')string(...)delimiter(')operator(;)
+
+operator(@)ident(unlink)operator(()local_variable($filename)operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(Can't delete, )operator({)local_variable($filename)operator(})string(!)char(\\n)delimiter(")operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($files) operator(=) ident(glob)operator(()delimiter(')string(...)delimiter(')operator(\))operator(;)
+local_variable($problem) operator(=) constant(FALSE)operator(;)
+
+comment(// Could simply use a foreach loop)
+reserved(foreach)operator(()local_variable($files) reserved(as) local_variable($filename)operator(\)) operator({) operator(@)ident(unlink)operator(()local_variable($filename)operator(\)) operator(|)operator(|) local_variable($problem) operator(=) constant(TRUE)operator(;) operator(})
+
+comment(//)
+comment(// Alternatively, an applicative approach could be used, one closer in spirit to)
+comment(// largely-functional languages like Scheme)
+comment(//)
+comment(// function is_all_deleted($deleted, $filename\) { return @unlink($filename\) && $deleted; })
+comment(// $problem = !array_reduce($files, 'is_all_deleted', TRUE\);)
+comment(//)
+
+reserved(if) operator(()local_variable($problem)operator(\))
+operator({)
+ ident(fwrite)operator(()constant(STDERR)operator(,) delimiter(')string(Could not delete all of:)delimiter(')operator(\))operator(;)
+ reserved(foreach)operator(()local_variable($files) reserved(as) local_variable($filename)operator(\)) operator({) ident(fwrite)operator(()constant(STDERR)operator(,) delimiter(')string( )delimiter(') operator(.) local_variable($filename)operator(\))operator(;) operator(})
+ ident(fwrite)operator(()constant(STDERR)operator(,) delimiter(")char(\\n)delimiter(")operator(\))operator(;) reserved(exit)operator(()integer(1)operator(\))operator(;)
+operator(})
+
+comment(// ------------)
+
+pre_type(function) ident(rmAll)operator(()local_variable($files)operator(\))
+operator({)
+ local_variable($count) operator(=) integer(0)operator(;)
+
+ reserved(foreach)operator(()local_variable($files) reserved(as) local_variable($filename)operator(\)) operator({) operator(@)ident(unlink)operator(()local_variable($filename)operator(\)) operator(&)operator(&) local_variable($count)operator(++)operator(;) operator(})operator(;)
+
+ reserved(return) local_variable($count)operator(;)
+
+comment(// An applicative alternative using 'create_function', PHP's rough equivalent of 'lambda' ...)
+comment(//)
+comment(// return array_reduce($files,)
+comment(// create_function('$count, $filename', 'return @unlink($filename\) && $count++;'\), 0\);)
+operator(})
+
+comment(// ----)
+
+local_variable($files) operator(=) ident(glob)operator(()delimiter(')string(...)delimiter(')operator(\))operator(;)
+local_variable($toBeDeleted) operator(=) ident(sizeof)operator(()local_variable($files)operator(\))operator(;)
+local_variable($count) operator(=) ident(rmAll)operator(()local_variable($files)operator(\))operator(;)
+
+operator(()local_variable($count) operator(==) local_variable($toBeDeleted)operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(Could only delete )operator({)local_variable($count)operator(})string( of )operator({)local_variable($toBeDeleted)operator(})string( files)char(\\n)delimiter(")operator(\))operator(;)
+
+comment(// @@PLEAC@@_9.3)
+local_variable($oldfile) operator(=) delimiter(')string(/tmp/old)delimiter(')operator(;) local_variable($newfile) operator(=) delimiter(')string(/tmp/new)delimiter(')operator(;)
+
+ident(copy)operator(()local_variable($oldfile)operator(,) local_variable($newfile)operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(Error copying file)char(\\n)delimiter(")operator(\))operator(;)
+
+comment(// ----------------------------)
+
+comment(// All the following copy a file by copying its contents. Examples do so in a single)
+comment(// operation, but it is also possible to copy arbitrary blocks, or, line-by-line in )
+comment(// the case of 'text' files)
+local_variable($oldfile) operator(=) delimiter(')string(/tmp/old)delimiter(')operator(;) local_variable($newfile) operator(=) delimiter(')string(/tmp/new)delimiter(')operator(;)
+
+reserved(if) operator(()ident(is_file)operator(()local_variable($oldfile)operator(\))operator(\))
+ ident(file_put_contents)operator(()local_variable($newfile)operator(,) ident(file_get_contents)operator(()local_variable($oldfile)operator(\))operator(\))operator(;)
+reserved(else)
+ reserved(die)operator(()delimiter(")string(Problem copying file )operator({)local_variable($oldfile)operator(})string( to file )operator({)local_variable($newfile)operator(})char(\\n)delimiter(")operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($oldfile) operator(=) delimiter(')string(/tmp/old)delimiter(')operator(;) local_variable($newfile) operator(=) delimiter(')string(/tmp/new)delimiter(')operator(;)
+
+ident(fwrite)operator(()operator(()local_variable($nh) operator(=) ident(fopen)operator(()local_variable($newfile)operator(,) delimiter(')string(wb)delimiter(')operator(\))operator(\))operator(,) ident(fread)operator(()operator(()local_variable($oh) operator(=) ident(fopen)operator(()local_variable($oldfile)operator(,) delimiter(')string(rb)delimiter(')operator(\))operator(\))operator(,) ident(filesize)operator(()local_variable($oldfile)operator(\))operator(\))operator(\))operator(;)
+ident(fclose)operator(()local_variable($oh)operator(\))operator(;)
+ident(fclose)operator(()local_variable($nh)operator(\))operator(;)
+
+comment(// ------------)
+
+comment(// As above, but with some error checking / handling)
+local_variable($oldfile) operator(=) delimiter(')string(/tmp/old)delimiter(')operator(;) local_variable($newfile) operator(=) delimiter(')string(/tmp/new)delimiter(')operator(;)
+
+operator(()local_variable($oh) operator(=) ident(fopen)operator(()local_variable($oldfile)operator(,) delimiter(')string(rb)delimiter(')operator(\))operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(Problem opening input file )operator({)local_variable($oldfile)operator(})char(\\n)delimiter(")operator(\))operator(;)
+operator(()local_variable($nh) operator(=) ident(fopen)operator(()local_variable($newfile)operator(,) delimiter(')string(wb)delimiter(')operator(\))operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(Problem opening output file )operator({)local_variable($newfile)operator(})char(\\n)delimiter(")operator(\))operator(;)
+
+reserved(if) operator(()operator(()local_variable($filesize) operator(=) ident(filesize)operator(()local_variable($oldfile)operator(\))operator(\)) operator(>) integer(0)operator(\))
+operator({)
+ ident(fwrite)operator(()local_variable($nh)operator(,) ident(fread)operator(()local_variable($oh)operator(,) local_variable($filesize)operator(\))operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(Problem reading / writing file data)char(\\n)delimiter(")operator(\))operator(;)
+operator(})
+
+ident(fclose)operator(()local_variable($oh)operator(\))operator(;)
+ident(fclose)operator(()local_variable($nh)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+comment(// Should there be platform-specfic problems copying 'very large' files, it is)
+comment(// a simple matter to call a system command utility via, 'exec')
+
+comment(// *NIX-specific example. Could check whether, 'exec', succeeded, but checking whether)
+comment(// a file exists after the operation might be a better approach)
+local_variable($oldfile) operator(=) delimiter(')string(/tmp/old)delimiter(')operator(;) local_variable($newfile) operator(=) delimiter(')string(/tmp/new)delimiter(')operator(;)
+
+ident(is_file)operator(()local_variable($newfile)operator(\)) operator(&)operator(&) ident(unlink)operator(()local_variable($newfile)operator(\))operator(;)
+
+ident(exec)operator(()ident(trim)operator(()delimiter(')string(cp --force )delimiter(') operator(.) ident(escapeshellarg)operator(()local_variable($oldfile)operator(\)) operator(.) delimiter(')string( )delimiter(') operator(.) ident(escapeshellarg)operator(()local_variable($newfile)operator(\))operator(\))operator(\))operator(;)
+
+ident(is_file)operator(()local_variable($newfile)operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(Problem copying file )operator({)local_variable($oldfile)operator(})string( to file )operator({)local_variable($newfile)operator(})char(\\n)delimiter(")operator(\))operator(;)
+
+comment(// For other operating systems just change:)
+comment(// * filenames)
+comment(// * command being 'exec'ed)
+comment(// as the rest of the code is platform independant)
+
+comment(// @@PLEAC@@_9.4)
+pre_type(function) ident(makeDevInodePair)operator(()local_variable($filename)operator(\))
+operator({)
+ reserved(if) operator(()operator(!)operator(()local_variable($fs) operator(=) operator(@)ident(stat)operator(()local_variable($filename)operator(\))operator(\))operator(\)) reserved(return) constant(FALSE)operator(;)
+ reserved(return) ident(strval)operator(()local_variable($fs)operator([)delimiter(')string(dev)delimiter(')operator(]) operator(.) local_variable($fs)operator([)delimiter(')string(ino)delimiter(')operator(])operator(\))operator(;)
+operator(})
+
+comment(// ------------)
+
+pre_type(function) ident(do_my_thing)operator(()local_variable($filename)operator(\))
+operator({)
+ comment(// Using a global variable to mimic Perl example, but could easily have passed)
+ comment(// '$seen' as an argument)
+ pre_type(global) local_variable($seen)operator(;)
+
+ local_variable($devino) operator(=) ident(makeDevInodePair)operator(()local_variable($filename)operator(\))operator(;)
+
+ comment(// Process $filename if it has not previously been seen, else just increment)
+ reserved(if) operator(()operator(!)pre_type(isset)operator(()local_variable($seen)operator([)local_variable($devino)operator(])operator(\))operator(\))
+ operator({)
+ comment(// ... process $filename ...)
+
+ comment(// Set initial count)
+ local_variable($seen)operator([)local_variable($devino)operator(]) operator(=) integer(1)operator(;)
+ operator(})
+ reserved(else)
+ operator({)
+ comment(// Otherwise, just increment the count)
+ local_variable($seen)operator([)local_variable($devino)operator(]) operator(+)operator(=) integer(1)operator(;)
+ operator(})
+operator(})
+
+comment(// ----)
+
+comment(// Simple example)
+local_variable($seen) operator(=) pre_type(array)operator(()operator(\))operator(;)
+
+ident(do_my_thing)operator(()delimiter(')string(/tmp/old)delimiter(')operator(\))operator(;)
+ident(do_my_thing)operator(()delimiter(')string(/tmp/old)delimiter(')operator(\))operator(;)
+ident(do_my_thing)operator(()delimiter(')string(/tmp/old)delimiter(')operator(\))operator(;)
+ident(do_my_thing)operator(()delimiter(')string(/tmp/new)delimiter(')operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($seen) reserved(as) local_variable($devino) operator(=>) local_variable($count)operator(\))
+operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($devino)operator(})string( -> )operator({)local_variable($count)operator(})char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// ------------)
+
+comment(// A variation on the above avoiding use of global variables, and illustrating use of)
+comment(// easily-implemented 'higher order' techniques)
+
+comment(// Helper function loosely modelled on, 'array_reduce', but using an array as)
+comment(// 'accumulator', which is returned on completion)
+pre_type(function) ident(array_update)operator(()local_variable($arr)operator(,) local_variable($lambda)operator(,) local_variable($updarr)operator(\))
+operator({)
+ reserved(foreach)operator(()local_variable($arr) reserved(as) local_variable($key)operator(\)) local_variable($lambda)operator(()local_variable($updarr)operator(,) local_variable($key)operator(\))operator(;)
+ reserved(return) local_variable($updarr)operator(;)
+operator(})
+
+pre_type(function) ident(do_my_thing)operator(()operator(&)local_variable($seen)operator(,) local_variable($filename)operator(\))
+operator({)
+ reserved(if) operator(()operator(!)ident(array_key_exists)operator(()operator(()local_variable($devino) operator(=) ident(makeDevInodePair)operator(()local_variable($filename)operator(\))operator(\))operator(,) local_variable($seen)operator(\))operator(\))
+ operator({)
+ comment(// ... processing $filename ...)
+
+ comment(// Update $seen)
+ local_variable($seen)operator([)local_variable($devino)operator(]) operator(=) integer(1)operator(;)
+ operator(})
+ reserved(else)
+ operator({)
+ comment(// Update $seen)
+ local_variable($seen)operator([)local_variable($devino)operator(]) operator(+)operator(=) integer(1)operator(;)
+ operator(})
+operator(})
+
+comment(// ----)
+
+comment(// Simple example)
+local_variable($files) operator(=) pre_type(array)operator(()delimiter(')string(/tmp/old)delimiter(')operator(,) delimiter(')string(/tmp/old)delimiter(')operator(,) delimiter(')string(/tmp/old)delimiter(')operator(,) delimiter(')string(/tmp/new)delimiter(')operator(\))operator(;)
+
+comment(// Could do this ...)
+local_variable($seen) operator(=) pre_type(array)operator(()operator(\))operator(;)
+ident(array_update)operator(()local_variable($files)operator(,) delimiter(')string(do_my_thing)delimiter(')operator(,) operator(&)local_variable($seen)operator(\))operator(;)
+
+comment(// or this:)
+local_variable($seen) operator(=) ident(array_update)operator(()local_variable($files)operator(,) delimiter(')string(do_my_thing)delimiter(')operator(,) pre_type(array)operator(()operator(\))operator(\))operator(;)
+
+comment(// or a 'lambda' could be used:)
+ident(array_update)operator(()local_variable($files)operator(,)
+ ident(create_function)operator(()delimiter(')string($seen, $filename)delimiter(')operator(,) delimiter(')string(... code not shown ...)delimiter(')operator(\))operator(,)
+ operator(&)local_variable($seen)operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($seen) reserved(as) local_variable($devino) operator(=>) local_variable($count)operator(\))
+operator({)
+ pre_type(echo) delimiter(")operator({)local_variable($devino)operator(})string( -> )operator({)local_variable($count)operator(})char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// ----------------------------)
+
+local_variable($files) operator(=) ident(glob)operator(()delimiter(')string(/tmp/*)delimiter(')operator(\))operator(;)
+
+ident(define)operator(()constant(SEP)operator(,) delimiter(')string(;)delimiter(')operator(\))operator(;)
+local_variable($seen) operator(=) pre_type(array)operator(()operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($files) reserved(as) local_variable($filename)operator(\))
+operator({)
+ reserved(if) operator(()operator(!)ident(array_key_exists)operator(()operator(()local_variable($devino) operator(=) ident(makeDevInodePair)operator(()local_variable($filename)operator(\))operator(\))operator(,) local_variable($seen)operator(\))operator(\))
+ local_variable($seen)operator([)local_variable($devino)operator(]) operator(=) local_variable($filename)operator(;)
+ reserved(else)
+ local_variable($seen)operator([)local_variable($devino)operator(]) operator(=) local_variable($seen)operator([)local_variable($devino)operator(]) operator(.) constant(SEP) operator(.) local_variable($filename)operator(;)
+operator(})
+
+local_variable($devino) operator(=) ident(array_keys)operator(()local_variable($seen)operator(\))operator(;)
+ident(sort)operator(()local_variable($devino)operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($devino) reserved(as) local_variable($key)operator(\))
+operator({)
+ pre_type(echo) local_variable($key) operator(.) delimiter(')string(:)delimiter(')operator(;)
+ reserved(foreach)operator(()ident(split)operator(()constant(SEP)operator(,) local_variable($seen)operator([)local_variable($key)operator(])operator(\)) reserved(as) local_variable($filename)operator(\)) pre_type(echo) delimiter(')string( )delimiter(') operator(.) local_variable($filename)operator(;)
+ pre_type(echo) delimiter(")char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// @@PLEAC@@_9.5)
+comment(// Conventional POSIX-like approach to directory traversal)
+local_variable($dirname) operator(=) delimiter(')string(/usr/bin/)delimiter(')operator(;)
+
+operator(()local_variable($dirhdl) operator(=) ident(opendir)operator(()local_variable($dirname)operator(\))operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(Couldn't open )operator({)local_variable($dirname)operator(})char(\\n)delimiter(")operator(\))operator(;)
+
+reserved(while) operator(()operator(()local_variable($file) operator(=) ident(readdir)operator(()local_variable($dirhdl)operator(\))operator(\)) operator(!==) constant(FALSE)operator(\))
+operator({)
+ operator(;) comment(// ... do something with $dirname/$file)
+ comment(// ...)
+operator(})
+
+ident(closedir)operator(()local_variable($dirhdl)operator(\))operator(;)
+
+comment(// ------------)
+
+comment(// Newer [post PHP 4], 'applicative' approach - an array of filenames is)
+comment(// generated that may be processed via external loop ...)
+
+local_variable($dirname) operator(=) delimiter(')string(/usr/bin/)delimiter(')operator(;)
+
+reserved(foreach)operator(()ident(scandir)operator(()local_variable($dirname)operator(\)) reserved(as) local_variable($file)operator(\))
+operator({)
+ operator(;) comment(// ... do something with $dirname/$file)
+ comment(// ...)
+operator(})
+
+comment(// .. or, via callback application, perhaps after massaging by one of the)
+comment(// 'array' family of functions [also uses, 'array_update', from earlier section])
+
+local_variable($newlist) operator(=) ident(array_update)operator(()ident(array_reverse)operator(()ident(scandir)operator(()local_variable($dirname)operator(\))operator(\))operator(,)
+ ident(create_function)operator(()delimiter(')string($filelist, $file)delimiter(')operator(,) delimiter(')string( ; )delimiter(')operator(\))operator(,)
+ pre_type(array)operator(()operator(\))operator(\))operator(;)
+
+comment(// And don't forget that the old standby, 'glob', that returns an array of)
+comment(// paths filtered using the Bourne Shell-based wildcards, '?' and '*', is)
+comment(// also available)
+
+reserved(foreach)operator(()ident(glob)operator(()local_variable($dirname) operator(.) delimiter(')string(*)delimiter(')operator(\)) reserved(as) local_variable($path)operator(\))
+operator({)
+ operator(;) comment(// ... do something with $path)
+ comment(// ...)
+operator(})
+
+comment(// ----------------------------)
+
+comment(// Uses, 'isTextFile', from an earlier section)
+local_variable($dirname) operator(=) delimiter(')string(/usr/bin/)delimiter(')operator(;)
+
+pre_type(echo) delimiter(")string(Text files in )operator({)local_variable($dirname)operator(})string(:)char(\\n)delimiter(")operator(;)
+
+reserved(foreach)operator(()ident(scandir)operator(()local_variable($dirname)operator(\)) reserved(as) local_variable($file)operator(\))
+operator({)
+ comment(// Take care when constructing paths to ensure cross-platform operability )
+ local_variable($path) operator(=) local_variable($dirname) operator(.) local_variable($file)operator(;)
+
+ reserved(if) operator(()ident(is_file)operator(()local_variable($path)operator(\)) operator(&)operator(&) ident(isTextFile)operator(()local_variable($path)operator(\))operator(\)) pre_type(echo) local_variable($path) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// ----------------------------)
+
+pre_type(function) ident(plain_files)operator(()local_variable($dirname)operator(\))
+operator({)
+ operator(()local_variable($dirlist) operator(=) ident(glob)operator(()local_variable($dirname) operator(.) delimiter(')string(*)delimiter(')operator(\))operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(Couldn't glob )operator({)local_variable($dirname)operator(})char(\\n)delimiter(")operator(\))operator(;)
+
+ comment(// Pass function name directly if only a single function performs filter test)
+ reserved(return) ident(array_filter)operator(()local_variable($dirlist)operator(,) delimiter(')string(is_file)delimiter(')operator(\))operator(;)
+
+ comment(// Use, 'create_function', if a multi-function test is needed)
+ comment(//)
+ comment(// return array_filter($dirlist, create_function('$path', 'return is_file($path\);'\)\);)
+ comment(//)
+operator(})
+
+comment(// ------------)
+
+reserved(foreach)operator(()ident(plain_files)operator(()delimiter(')string(/tmp/)delimiter(')operator(\)) reserved(as) local_variable($path)operator(\))
+operator({)
+ pre_type(echo) local_variable($path) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// @@PLEAC@@_9.6)
+local_variable($dirname) operator(=) delimiter(')string(/tmp/)delimiter(')operator(;)
+
+comment(// Full paths)
+local_variable($pathlist) operator(=) ident(glob)operator(()local_variable($dirname) operator(.) delimiter(')string(*.c)delimiter(')operator(\))operator(;)
+
+comment(// File names only - glob-based matching)
+local_variable($filelist) operator(=) ident(array_filter)operator(()ident(scandir)operator(()local_variable($dirname)operator(\))operator(,)
+ ident(create_function)operator(()delimiter(')string($file)delimiter(')operator(,) delimiter(')string(return fnmatch("*.c", $file\);)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// ----------------------------)
+
+local_variable($dirname) operator(=) delimiter(')string(/tmp/)delimiter(')operator(;)
+
+comment(// File names only - regex-based matching [case-insensitive])
+local_variable($filelist) operator(=) ident(array_filter)operator(()ident(scandir)operator(()local_variable($dirname)operator(\))operator(,)
+ ident(create_function)operator(()delimiter(')string($file)delimiter(')operator(,) delimiter(')string(return eregi(")string(\\)string(.[ch]$", $file\);)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// ----------------------------)
+
+local_variable($dirname) operator(=) delimiter(')string(/tmp/)delimiter(')operator(;)
+
+comment(// Directory names - all-digit names)
+local_variable($dirs) operator(=) ident(array_filter)operator(()ident(glob)operator(()local_variable($dirname) operator(.) delimiter(')string(*)delimiter(')operator(,) constant(GLOB_ONLYDIR)operator(\))operator(,)
+ ident(create_function)operator(()delimiter(')string($path)delimiter(')operator(,) delimiter(')string(return ereg("^[0-9]+$", basename($path\)\);)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// @@PLEAC@@_9.7)
+comment(// Recursive directory traversal function and helper: traverses a directory tree)
+comment(// applying a function [and a variable number of accompanying arguments] to each)
+comment(// file)
+
+pre_type(class) constant(Accumulator)
+operator({)
+ pre_type(public) local_variable($value)operator(;)
+ pre_type(public) pre_type(function) ident(__construct)operator(()local_variable($start_value)operator(\)) operator({) local_variable($this)operator(->)ident(value) operator(=) local_variable($start_value)operator(;) operator(})
+operator(})
+
+comment(// ------------)
+
+pre_type(function) ident(process_directory_)operator(()local_variable($op)operator(,) local_variable($func_args)operator(\))
+operator({)
+ reserved(if) operator(()ident(is_dir)operator(()local_variable($func_args)operator([)integer(0)operator(])operator(\))operator(\))
+ operator({)
+ local_variable($current) operator(=) local_variable($func_args)operator([)integer(0)operator(])operator(;)
+ reserved(foreach)operator(()ident(scandir)operator(()local_variable($current)operator(\)) reserved(as) local_variable($entry)operator(\))
+ operator({)
+ reserved(if) operator(()local_variable($entry) operator(==) delimiter(')string(.)delimiter(') operator(|)operator(|) local_variable($entry) operator(==) delimiter(')string(..)delimiter(')operator(\)) reserved(continue)operator(;)
+ local_variable($func_args)operator([)integer(0)operator(]) operator(=) local_variable($current) operator(.) delimiter(')string(/)delimiter(') operator(.) local_variable($entry)operator(;)
+ ident(process_directory_)operator(()local_variable($op)operator(,) local_variable($func_args)operator(\))operator(;)
+ operator(})
+ operator(})
+ reserved(else)
+ operator({)
+ ident(call_user_func_array)operator(()local_variable($op)operator(,) local_variable($func_args)operator(\))operator(;)
+ operator(})
+operator(})
+
+pre_type(function) ident(process_directory)operator(()local_variable($op)operator(,) local_variable($dir)operator(\))
+operator({)
+ reserved(if) operator(()operator(!)ident(is_dir)operator(()local_variable($dir)operator(\))operator(\)) reserved(return) constant(FALSE)operator(;)
+ local_variable($func_args) operator(=) ident(array_slice)operator(()ident(func_get_args)operator(()operator(\))operator(,) integer(1)operator(\))operator(;)
+ ident(process_directory_)operator(()local_variable($op)operator(,) local_variable($func_args)operator(\))operator(;)
+ reserved(return) constant(TRUE)operator(;)
+operator(})
+
+comment(// ----------------------------)
+
+local_variable($dirlist) operator(=) pre_type(array)operator(()delimiter(')string(/tmp/d1)delimiter(')operator(,) delimiter(')string(/tmp/d2)delimiter(')operator(,) delimiter(')string(/tmp/d3)delimiter(')operator(\))operator(;)
+
+comment(// Do something with each directory in the list)
+reserved(foreach)operator(()local_variable($dirlist) reserved(as) local_variable($dir)operator(\))
+operator({)
+ operator(;)
+ comment(// Delete directory [if empty] -> rmdir($dir\); )
+ comment(// Make it the 'current directory' -> chdir($dir\);)
+ comment(// Get list of files it contains -> $filelist = scandir($dir\);)
+ comment(// Get directory metadata -> $ds = stat($dir\);)
+operator(})
+
+comment(// ------------)
+
+local_variable($dirlist) operator(=) pre_type(array)operator(()delimiter(')string(/tmp/d1)delimiter(')operator(,) delimiter(')string(/tmp/d2)delimiter(')operator(,) delimiter(')string(/tmp/d3)delimiter(')operator(\))operator(;)
+
+pre_type(function) ident(pf)operator(()local_variable($path)operator(\))
+operator({)
+ comment(// ... do something to the file or directory ...)
+ ident(printf)operator(()delimiter(")string(%s)char(\\n)delimiter(")operator(,) local_variable($path)operator(\))operator(;)
+operator(})
+
+comment(// For each directory in the list ...)
+reserved(foreach)operator(()local_variable($dirlist) reserved(as) local_variable($dir)operator(\))
+operator({)
+ comment(// Is this a valid directory ?)
+ reserved(if) operator(()operator(!)ident(is_dir)operator(()local_variable($dir)operator(\))operator(\)) operator({) ident(printf)operator(()delimiter(")string(%s does not exist)char(\\n)delimiter(")operator(,) local_variable($dir)operator(\))operator(;) reserved(continue)operator(;) operator(})
+
+ comment(// Ok, so get all the directory's entries)
+ local_variable($filelist) operator(=) ident(scandir)operator(()local_variable($dir)operator(\))operator(;)
+
+ comment(// An 'empty' directory will contain at least two entries: '..' and '.')
+ reserved(if) operator(()ident(count)operator(()local_variable($filelist)operator(\)) operator(==) integer(2)operator(\)) operator({) ident(printf)operator(()delimiter(")string(%s is empty)char(\\n)delimiter(")operator(,) local_variable($dir)operator(\))operator(;) reserved(continue)operator(;) operator(})
+
+ comment(// For each file / directory in the directory ...)
+ reserved(foreach)operator(()local_variable($filelist) reserved(as) local_variable($file)operator(\))
+ operator({)
+ comment(// Ignore '..' and '.' entries)
+ reserved(if) operator(()local_variable($file) operator(==) delimiter(')string(.)delimiter(') operator(|)operator(|) local_variable($file) operator(==) delimiter(')string(..)delimiter(')operator(\)) reserved(continue)operator(;)
+
+ comment(// Apply function to process the file / directory)
+ ident(pf)operator(()local_variable($dir) operator(.) delimiter(')string(/)delimiter(') operator(.) local_variable($file)operator(\))operator(;)
+ operator(})
+operator(})
+
+comment(// ----------------------------)
+
+pre_type(function) ident(accum_filesize)operator(()local_variable($file)operator(,) local_variable($accum)operator(\))
+operator({)
+ ident(is_file)operator(()local_variable($file)operator(\)) operator(&)operator(&) operator(()local_variable($accum)operator(->)ident(value) operator(+)operator(=) ident(filesize)operator(()local_variable($file)operator(\))operator(\))operator(;)
+operator(})
+
+comment(// ------------)
+
+comment(// Verify arguments ...)
+local_variable($argc) operator(==) integer(2) operator(|)operator(|) reserved(die)operator(()delimiter(")string(usage: )operator({)local_variable($argv)operator([)integer(0)operator(])operator(})string( dir)char(\\n)delimiter(")operator(\))operator(;)
+local_variable($dir) operator(=) local_variable($argv)operator([)integer(1)operator(])operator(;)
+
+ident(is_dir)operator(()local_variable($dir)operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")operator({)local_variable($dir)operator(})string( does not exist / not a directory)char(\\n)delimiter(")operator(\))operator(;)
+
+comment(// Collect data [use an object to accumulate results])
+local_variable($dirsize) operator(=) pre_type(new) constant(Accumulator)operator(()integer(0)operator(\))operator(;)
+ident(process_directory)operator(()delimiter(')string(accum_filesize)delimiter(')operator(,) local_variable($dir)operator(,) local_variable($dirsize)operator(\))operator(;)
+
+comment(// Report results)
+ident(printf)operator(()delimiter(")string(%s contains %d bytes)char(\\n)delimiter(")operator(,) local_variable($dir)operator(,) local_variable($dirsize)operator(->)ident(value)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(biggest_file)operator(()local_variable($file)operator(,) local_variable($accum)operator(\))
+operator({)
+ reserved(if) operator(()ident(is_file)operator(()local_variable($file)operator(\))operator(\))
+ operator({)
+ local_variable($fs) operator(=) ident(filesize)operator(()local_variable($file)operator(\))operator(;)
+ reserved(if) operator(()local_variable($accum)operator(->)ident(value)operator([)integer(1)operator(]) operator(<) local_variable($fs)operator(\)) operator({) local_variable($accum)operator(->)ident(value)operator([)integer(0)operator(]) operator(=) local_variable($file)operator(;) local_variable($accum)operator(->)ident(value)operator([)integer(1)operator(]) operator(=) local_variable($fs)operator(;) operator(})
+ operator(})
+operator(})
+
+comment(// ------------)
+
+comment(// Verify arguments ...)
+local_variable($argc) operator(==) integer(2) operator(|)operator(|) reserved(die)operator(()delimiter(")string(usage: )operator({)local_variable($argv)operator([)integer(0)operator(])operator(})string( dir)char(\\n)delimiter(")operator(\))operator(;)
+local_variable($dir) operator(=) local_variable($argv)operator([)integer(1)operator(])operator(;)
+
+ident(is_dir)operator(()local_variable($dir)operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")operator({)local_variable($dir)operator(})string( does not exist / not a directory)char(\\n)delimiter(")operator(\))operator(;)
+
+comment(// Collect data [use an object to accumulate results])
+local_variable($biggest) operator(=) pre_type(new) constant(Accumulator)operator(()pre_type(array)operator(()delimiter(')delimiter(')operator(,) integer(0)operator(\))operator(\))operator(;)
+ident(process_directory)operator(()delimiter(')string(biggest_file)delimiter(')operator(,) local_variable($dir)operator(,) local_variable($biggest)operator(\))operator(;)
+
+comment(// Report results)
+ident(printf)operator(()delimiter(")string(Biggest file is %s containing %d bytes)char(\\n)delimiter(")operator(,) local_variable($biggest)operator(->)ident(value)operator([)integer(0)operator(])operator(,) local_variable($biggest)operator(->)ident(value)operator([)integer(1)operator(])operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(youngest_file)operator(()local_variable($file)operator(,) local_variable($accum)operator(\))
+operator({)
+ reserved(if) operator(()ident(is_file)operator(()local_variable($file)operator(\))operator(\))
+ operator({)
+ local_variable($fct) operator(=) ident(filectime)operator(()local_variable($file)operator(\))operator(;)
+ reserved(if) operator(()local_variable($accum)operator(->)ident(value)operator([)integer(1)operator(]) operator(>) local_variable($fct)operator(\)) operator({) local_variable($accum)operator(->)ident(value)operator([)integer(0)operator(]) operator(=) local_variable($file)operator(;) local_variable($accum)operator(->)ident(value)operator([)integer(1)operator(]) operator(=) local_variable($fct)operator(;) operator(})
+ operator(})
+operator(})
+
+comment(// ------------)
+
+comment(// Verify arguments ...)
+local_variable($argc) operator(==) integer(2) operator(|)operator(|) reserved(die)operator(()delimiter(")string(usage: )operator({)local_variable($argv)operator([)integer(0)operator(])operator(})string( dir)char(\\n)delimiter(")operator(\))operator(;)
+local_variable($dir) operator(=) local_variable($argv)operator([)integer(1)operator(])operator(;)
+
+ident(is_dir)operator(()local_variable($dir)operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")operator({)local_variable($dir)operator(})string( does not exist / not a directory)char(\\n)delimiter(")operator(\))operator(;)
+
+comment(// Collect data [use an object to accumulate results])
+local_variable($youngest) operator(=) pre_type(new) constant(Accumulator)operator(()pre_type(array)operator(()delimiter(')delimiter(')operator(,) integer(2147483647)operator(\))operator(\))operator(;)
+ident(process_directory)operator(()delimiter(')string(youngest_file)delimiter(')operator(,) local_variable($dir)operator(,) local_variable($youngest)operator(\))operator(;)
+
+comment(// Report results)
+ident(printf)operator(()delimiter(")string(Youngest file is %s dating %s)char(\\n)delimiter(")operator(,) local_variable($youngest)operator(->)ident(value)operator([)integer(0)operator(])operator(,) ident(date)operator(()constant(DATE_ATOM)operator(,) local_variable($youngest)operator(->)ident(value)operator([)integer(1)operator(])operator(\))operator(\))operator(;)
+
+comment(// @@PLEAC@@_9.8)
+comment(// AFAICT, there is currently no library function that recursively removes a)
+comment(// directory tree [i.e. a directory, it's subdirectories, and any other files])
+comment(// with a single call. Such a function needs to be custom built. PHP tools)
+comment(// with which to do this:)
+comment(// * 'unlink', 'rmdir', 'is_dir', and 'is_file' functions, will all take care)
+comment(// of the file testing and deletion)
+comment(// * Actual directory traversal requires obtaining directory / subdirectory)
+comment(// lists, and here there is much choice available, though care must be taken)
+comment(// as each has it's own quirks)
+comment(// - 'opendir', 'readdir', 'closedir')
+comment(// - 'scandir')
+comment(// - 'glob')
+comment(// - SPL 'directory iterator' classes [newish / experimental - not shown here])
+comment(//)
+comment(// The PHP documentation for 'rmdir' contains several examples, each illustrating)
+comment(// one of each approach; the example shown here is loosely based on one of these)
+comment(// examples)
+
+comment(// Recursor - recursively traverses directory tree)
+pre_type(function) ident(rmtree_)operator(()local_variable($dir)operator(\))
+operator({)
+ local_variable($dir) operator(=) delimiter(")local_variable($dir)delimiter(")operator(;)
+
+ reserved(if) operator(()local_variable($dh) operator(=) ident(opendir)operator(()local_variable($dir)operator(\))operator(\))
+ operator({)
+ reserved(while) operator(()constant(FALSE) operator(!==) operator(()local_variable($item) operator(=) ident(readdir)operator(()local_variable($dh)operator(\))operator(\))operator(\))
+ operator({)
+ reserved(if) operator(()local_variable($item) operator(!=) delimiter(')string(.)delimiter(') operator(&)operator(&) local_variable($item) operator(!=) delimiter(')string(..)delimiter(')operator(\))
+ operator({)
+ local_variable($subdir) operator(=) local_variable($dir) operator(.) delimiter(')string(/)delimiter(') operator(.) delimiter(")local_variable($item)delimiter(")operator(;)
+
+ reserved(if) operator(()ident(is_dir)operator(()local_variable($subdir)operator(\))operator(\)) ident(rmtree_)operator(()local_variable($subdir)operator(\))operator(;)
+ reserved(else) operator(@)ident(unlink)operator(()local_variable($subdir)operator(\))operator(;)
+ operator(})
+ operator(})
+
+ ident(closedir)operator(()local_variable($dh)operator(\))operator(;) operator(@)ident(rmdir)operator(()local_variable($dir)operator(\))operator(;)
+ operator(})
+operator(})
+
+comment(// Launcher - performs validation then starts recursive routine)
+pre_type(function) ident(rmtree)operator(()local_variable($dir)operator(\))
+operator({)
+ reserved(if) operator(()ident(is_dir)operator(()local_variable($dir)operator(\))operator(\))
+ operator({)
+ operator(()ident(substr)operator(()local_variable($dir)operator(,) integer(-1)operator(,) integer(1)operator(\)) operator(==) delimiter(')string(/)delimiter(')operator(\)) operator(&)operator(&) operator(()local_variable($dir) operator(=) ident(substr)operator(()local_variable($dir)operator(,) integer(0)operator(,) integer(-1)operator(\))operator(\))operator(;)
+ ident(rmtree_)operator(()local_variable($dir)operator(\))operator(;) reserved(return) operator(!)ident(is_dir)operator(()local_variable($dir)operator(\))operator(;)
+ operator(})
+
+ reserved(return) constant(FALSE)operator(;)
+operator(})
+
+comment(// ------------)
+
+local_variable($argc) operator(==) integer(2) operator(|)operator(|) reserved(die)operator(()delimiter(")string(usage: rmtree dir)char(\\n)delimiter(")operator(\))operator(;)
+
+ident(rmtree)operator(()local_variable($argv)operator([)integer(1)operator(])operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(Could not remove directory )operator({)local_variable($argv)operator([)integer(1)operator(])operator(})char(\\n)delimiter(")operator(\))operator(;)
+
+comment(// @@PLEAC@@_9.9)
+local_variable($filepairs) operator(=) pre_type(array)operator(()delimiter(')string(x.txt)delimiter(') operator(=>) delimiter(')string(x2.txt)delimiter(')operator(,) delimiter(')string(y.txt)delimiter(') operator(=>) delimiter(')string(y.doc)delimiter(')operator(,) delimiter(')string(zxc.txt)delimiter(') operator(=>) delimiter(')string(cxz.txt)delimiter(')operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($filepairs) reserved(as) local_variable($oldfile) operator(=>) local_variable($newfile)operator(\))
+operator({)
+ operator(@)ident(rename)operator(()local_variable($oldfile)operator(,) local_variable($newfile)operator(\)) operator(|)operator(|) ident(fwrite)operator(()constant(STDERR)operator(,) ident(sprintf)operator(()delimiter(")string(Could not rename %s to %s)char(\\n)delimiter(")operator(,) local_variable($oldfile)operator(,) local_variable($newfile)operator(\))operator(\))operator(;)
+operator(})
+
+comment(// ----------------------------)
+
+comment(// Call a system command utility via, 'exec'. *NIX-specific example. Could check whether,)
+comment(// 'exec', succeeded, but checking whether a renamed file exists after the operation might)
+comment(// be a better approach)
+
+local_variable($oldfile) operator(=) delimiter(')string(/tmp/old)delimiter(')operator(;) local_variable($newfile) operator(=) delimiter(')string(/tmp/new)delimiter(')operator(;)
+
+ident(is_file)operator(()local_variable($newfile)operator(\)) operator(&)operator(&) ident(unlink)operator(()local_variable($newfile)operator(\))operator(;)
+
+ident(exec)operator(()ident(trim)operator(()delimiter(')string(mv --force )delimiter(') operator(.) ident(escapeshellarg)operator(()local_variable($oldfile)operator(\)) operator(.) delimiter(')string( )delimiter(') operator(.) ident(escapeshellarg)operator(()local_variable($newfile)operator(\))operator(\))operator(\))operator(;)
+
+ident(is_file)operator(()local_variable($oldfile)operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(Problem renaming file )operator({)local_variable($oldfile)operator(})string( to file )operator({)local_variable($newfile)operator(})char(\\n)delimiter(")operator(\))operator(;)
+
+comment(// For other operating systems just change:)
+comment(// * filenames)
+comment(// * command being 'exec'ed)
+comment(// as the rest of the code is platform independant)
+
+comment(// ----------------------------)
+
+comment(// A modified implementation of Larry's Filename Fixer. Rather than passing)
+comment(// a single expression, a 'from' regexp is passed; each match in the file)
+comment(// name(s\) is changed to the value of 'to'. It otherwise behaves the same)
+comment(//)
+
+local_variable($argc) operator(>) integer(2) operator(|)operator(|) reserved(die)operator(()delimiter(")string(usage: rename from to [file ...])char(\\n)delimiter(")operator(\))operator(;)
+
+local_variable($from) operator(=) local_variable($argv)operator([)integer(1)operator(])operator(;)
+local_variable($to) operator(=) local_variable($argv)operator([)integer(2)operator(])operator(;)
+
+reserved(if) operator(()ident(count)operator(()operator(()local_variable($argv) operator(=) ident(array_slice)operator(()local_variable($argv)operator(,) integer(3)operator(\))operator(\))operator(\)) operator(<) integer(1)operator(\))
+ reserved(while) operator(()operator(!)ident(feof)operator(()constant(STDIN)operator(\))operator(\)) local_variable($argv)operator([)operator(]) operator(=) ident(substr)operator(()ident(fgets)operator(()constant(STDIN)operator(\))operator(,) integer(0)operator(,) integer(-1)operator(\))operator(;)
+
+reserved(foreach)operator(()local_variable($argv) reserved(as) local_variable($file)operator(\))
+operator({)
+ local_variable($was) operator(=) local_variable($file)operator(;)
+ local_variable($file) operator(=) ident(ereg_replace)operator(()local_variable($from)operator(,) local_variable($to)operator(,) local_variable($file)operator(\))operator(;)
+
+ reserved(if) operator(()ident(strcmp)operator(()local_variable($was)operator(,) local_variable($file)operator(\)) operator(!=) integer(0)operator(\))
+ operator(@)ident(rename)operator(()local_variable($was)operator(,) local_variable($file)operator(\)) operator(|)operator(|) ident(fwrite)operator(()constant(STDERR)operator(,) ident(sprintf)operator(()delimiter(")string(Could not rename %s to %s)char(\\n)delimiter(")operator(,) local_variable($was)operator(,) local_variable($file)operator(\))operator(\))operator(;)
+operator(})
+
+comment(// @@PLEAC@@_9.10)
+local_variable($base) operator(=) ident(basename)operator(()local_variable($path)operator(\))operator(;)
+local_variable($dir) operator(=) ident(dirname)operator(()local_variable($path)operator(\))operator(;)
+
+comment(// PHP's equivalent to Perl's 'fileparse')
+local_variable($pathinfo) operator(=) ident(pathinfo)operator(()local_variable($path)operator(\))operator(;)
+
+local_variable($base) operator(=) local_variable($pathinfo)operator([)delimiter(')string(basename)delimiter(')operator(])operator(;)
+local_variable($dir) operator(=) local_variable($pathinfo)operator([)delimiter(')string(dirname)delimiter(')operator(])operator(;)
+local_variable($ext) operator(=) local_variable($pathinfo)operator([)delimiter(')string(extension)delimiter(')operator(])operator(;)
+
+comment(// ----------------------------)
+
+local_variable($path) operator(=) delimiter(')string(/usr/lib/libc.a)delimiter(')operator(;)
+
+ident(printf)operator(()delimiter(")string(dir is %s, file is %s)char(\\n)delimiter(")operator(,) ident(dirname)operator(()local_variable($path)operator(\))operator(,) ident(basename)operator(()local_variable($path)operator(\))operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($path) operator(=) delimiter(')string(/usr/lib/libc.a)delimiter(')operator(;)
+
+local_variable($pathinfo) operator(=) ident(pathinfo)operator(()local_variable($path)operator(\))operator(;)
+
+ident(printf)operator(()delimiter(")string(dir is %s, name is %s, extension is %s)char(\\n)delimiter(")operator(,) local_variable($pathinfo)operator([)delimiter(')string(dirname)delimiter(')operator(])operator(,) local_variable($pathinfo)operator([)delimiter(')string(basename)delimiter(')operator(])operator(,) local_variable($pathinfo)operator([)delimiter(')string(extension)delimiter(')operator(])operator(\))operator(;)
+
+comment(// ----------------------------)
+
+comment(// Handle Mac example as a simple parse task. However, AFAIK, 'pathinfo' is cross-platform,)
+comment(// so should handle file path format differences transparently)
+local_variable($path) operator(=) delimiter(')string(Hard%20Drive:System%20Folder:README.txt)delimiter(')operator(;)
+
+local_variable($macp) operator(=) ident(array_combine)operator(()pre_type(array)operator(()delimiter(')string(drive)delimiter(')operator(,) delimiter(')string(folder)delimiter(')operator(,) delimiter(')string(filename)delimiter(')operator(\))operator(,) ident(split)operator(()delimiter(")string(\\)string(:)delimiter(")operator(,) ident(str_replace)operator(()delimiter(')string(%20)delimiter(')operator(,) delimiter(')string( )delimiter(')operator(,) local_variable($path)operator(\))operator(\))operator(\))operator(;)
+local_variable($macf) operator(=) ident(array_combine)operator(()pre_type(array)operator(()delimiter(')string(name)delimiter(')operator(,) delimiter(')string(extension)delimiter(')operator(\))operator(,) ident(split)operator(()delimiter(")string(\\)string(.)delimiter(")operator(,) local_variable($macp)operator([)delimiter(')string(filename)delimiter(')operator(])operator(\))operator(\))operator(;)
+
+ident(printf)operator(()delimiter(")string(dir is %s, name is %s, extension is %s)char(\\n)delimiter(")operator(,) operator(()local_variable($macp)operator([)delimiter(')string(drive)delimiter(')operator(]) operator(.) delimiter(')string(:)delimiter(') operator(.) local_variable($macp)operator([)delimiter(')string(folder)delimiter(')operator(])operator(\))operator(,) local_variable($macf)operator([)delimiter(')string(name)delimiter(')operator(])operator(,) operator(()delimiter(')string(.)delimiter(') operator(.) local_variable($macf)operator([)delimiter(')string(extension)delimiter(')operator(])operator(\))operator(\))operator(;)
+
+comment(// ----------------------------)
+
+comment(// Not really necessary since we have, 'pathinfo', but better matches Perl example)
+pre_type(function) ident(file_extension)operator(()local_variable($filename)operator(,) local_variable($separator) operator(=) delimiter(')string(.)delimiter(')operator(\))
+operator({)
+ reserved(return) ident(end)operator(()ident(split)operator(()operator(()delimiter(")char(\\\\)delimiter(") operator(.) local_variable($separator)operator(\))operator(,) local_variable($filename)operator(\))operator(\))operator(;)
+operator(})
+
+comment(// ----)
+
+pre_type(echo) ident(file_extension)operator(()delimiter(')string(readme.txt)delimiter(')operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// @@PLEAC@@_9.11)
+comment(// @@INCOMPLETE@@)
+comment(// @@INCOMPLETE@@)
+
+comment(// @@PLEAC@@_9.12)
+comment(// @@INCOMPLETE@@)
+comment(// @@INCOMPLETE@@)
+
+comment(// @@PLEAC@@_10.0)
+comment(// Since defined at outermost scope, $greeted may be considered a global variable)
+local_variable($greeted) operator(=) integer(0)operator(;)
+
+comment(// ------------)
+
+comment(// Must use, 'global', keyword to inform functions that $greeted already exists as)
+comment(// a global variable. If this is not done, a local variable of that name is implicitly)
+comment(// defined)
+pre_type(function) ident(howManyGreetings)operator(()operator(\))
+operator({)
+ pre_type(global) local_variable($greeted)operator(;)
+ reserved(return) local_variable($greeted)operator(;)
+operator(})
+
+pre_type(function) ident(hello)operator(()operator(\))
+operator({)
+ pre_type(global) local_variable($greeted)operator(;)
+ local_variable($greeted)operator(++)operator(;)
+ pre_type(echo) delimiter(")string(high there!, this procedure has been called )operator({)local_variable($greeted)operator(})string( times)char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// ------------)
+
+ident(hello)operator(()operator(\))operator(;)
+local_variable($greetings) operator(=) ident(howManyGreetings)operator(()operator(\))operator(;)
+pre_type(echo) delimiter(")string(bye there!, there have been )operator({)local_variable($greetings)operator(})string( greetings so far)char(\\n)delimiter(")operator(;)
+
+comment(// @@PLEAC@@_10.1)
+comment(// Conventionally-defined function together with parameter list)
+pre_type(function) ident(hypotenuse)operator(()local_variable($side1)operator(,) local_variable($side2)operator(\))
+operator({)
+ reserved(return) ident(sqrt)operator(()ident(pow)operator(()local_variable($side1)operator(,) integer(2)operator(\)) operator(+) ident(pow)operator(()local_variable($side2)operator(,) integer(2)operator(\))operator(\))operator(;)
+operator(})
+
+comment(// ----)
+
+comment(// Alternative is to define the function without parameter list, then use)
+comment(// 'func_get_arg' to extract arguments)
+pre_type(function) ident(hypotenuse)operator(()operator(\))
+operator({)
+ comment(// Could check number of arguments passed with: 'func_num_args', which)
+ comment(// would be the approach used if dealing with variable number of arguments)
+ local_variable($side1) operator(=) ident(func_get_arg)operator(()integer(0)operator(\))operator(;) local_variable($side2) operator(=) ident(func_get_arg)operator(()integer(1)operator(\))operator(;)
+
+ reserved(return) ident(sqrt)operator(()ident(pow)operator(()local_variable($side1)operator(,) integer(2)operator(\)) operator(+) ident(pow)operator(()local_variable($side2)operator(,) integer(2)operator(\))operator(\))operator(;)
+operator(})
+
+comment(// ------------)
+
+comment(// 1. Conventional function call)
+local_variable($diag) operator(=) ident(hypotenuse)operator(()integer(3)operator(,) integer(4)operator(\))operator(;)
+
+comment(// ------------)
+
+comment(// 2. Function call using, 'call_user_func' library routines)
+local_variable($funcname) operator(=) delimiter(')string(hypotenuse)delimiter(')operator(;)
+
+comment(// a. Pass function name, and variable number of arguments)
+local_variable($diag) operator(=) ident(call_user_func)operator(()local_variable($funcname)operator(,) integer(3)operator(,) integer(4)operator(\))operator(;)
+
+comment(// b. Package arguments as array, pass together with function name)
+local_variable($args) operator(=) pre_type(array)operator(()integer(3)operator(,) integer(4)operator(\))operator(;)
+local_variable($diag) operator(=) ident(call_user_func_array)operator(()local_variable($funcname)operator(,) local_variable($args)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+local_variable($nums) operator(=) pre_type(array)operator(()integer(1)float(.4)operator(,) integer(3)float(.5)operator(,) integer(6)float(.7)operator(\))operator(;)
+
+comment(// ------------)
+
+comment(// Pass-by-value)
+pre_type(function) ident(int_all)operator(()local_variable($arr)operator(\))
+operator({)
+ reserved(return) ident(array_map)operator(()ident(create_function)operator(()delimiter(')string($n)delimiter(')operator(,) delimiter(')string(return (int\) $n;)delimiter(')operator(\))operator(,) local_variable($arr)operator(\))operator(;)
+operator(})
+
+comment(// Pass-by-reference)
+pre_type(function) ident(trunc_em)operator(()operator(&)local_variable($n)operator(\))
+operator({)
+ reserved(foreach) operator(()local_variable($n) reserved(as) operator(&)local_variable($value)operator(\)) local_variable($value) operator(=) operator(()ident(int)operator(\)) local_variable($value)operator(;)
+operator(})
+
+comment(// ------------)
+
+comment(// $nums untouched; $ints is new array)
+local_variable($ints) operator(=) ident(int_all)operator(()local_variable($nums)operator(\))operator(;)
+
+comment(// $nums updated)
+ident(trunc_em)operator(()local_variable($nums)operator(\))operator(;)
+
+comment(// @@PLEAC@@_10.2)
+comment(// Strictly-speaking, PHP is neither lexically [no environment capture] nor)
+comment(// dynamically [no variable shadowing] scoped. A script in which several)
+comment(// functions have been defined has two, entirely separate, scopes:)
+comment(//)
+comment(// * A 'top-level' scope i.e. everything outside each function)
+comment(//)
+comment(// * A 'local scope' within each function; each function is a self-contained)
+comment(// entity and cannot [via conventional means] access variables outside its)
+comment(// local scope. Accessing a variable that has not been locally defined)
+comment(// serves to define it i.e. accessing a variable assumed to be global)
+comment(// sees a local variable of that name defined)
+comment(//)
+comment(// The way 'global' variables are provided is via a predefined array of)
+comment(// variable names, $GLOBALS [it is one of a special set of variables known)
+comment(// as 'superglobals'; such variables *are* accessable in all scopes]. Each)
+comment(// entry in this array is a 'global' variable name, and may be freely)
+comment(// accessed / updated. A more convenient means of accessing such variables)
+comment(// is via the 'global' keyword: one or more variables within a function is)
+comment(// declared 'global', and those names are then taken to refer to entries)
+comment(// in the $GLOBALS array rather than seeing local variables of that name)
+comment(// accessed or defined)
+
+pre_type(function) ident(some_func)operator(()operator(\))
+operator({)
+ comment(// Variables declared within a function are local to that function)
+ local_variable($variable) operator(=) delimiter(')string(something)delimiter(')operator(;)
+operator(})
+
+comment(// ----------------------------)
+
+comment(// Top-level declared variables)
+local_variable($name) operator(=) local_variable($argv)operator([)integer(1)operator(])operator(;) local_variable($age) operator(=) local_variable($argv)operator([)integer(2)operator(])operator(;)
+
+local_variable($c) operator(=) ident(fetch_time)operator(()operator(\))operator(;)
+
+local_variable($condition) operator(=) integer(0)operator(;)
+
+comment(// ------------)
+
+pre_type(function) ident(run_check)operator(()operator(\))
+operator({)
+ comment(// The globally-declared variable, '$condition', is not accessable within)
+ comment(// the function unless it declared as 'global. Had this not been done then)
+ comment(// attempts to access, '$condition', would have seen a local variable)
+ comment(// of that name declared and updated. Same applies to other variables)
+ pre_type(global) local_variable($condition)operator(,) local_variable($name)operator(,) local_variable($age)operator(,) local_variable($c)operator(;)
+
+ local_variable($condition) operator(=) integer(1)operator(;)
+ comment(// ...)
+operator(})
+
+pre_type(function) ident(check_x)operator(()local_variable($x)operator(\))
+operator({)
+ local_variable($y) operator(=) delimiter(')string(whatever)delimiter(')operator(;)
+
+ comment(// This function only has access to the parameter, '$x', and the locally)
+ comment(// declared variable, '$y'.)
+
+ comment(// Whilst 'run_check' has access to several global variables, the current)
+ comment(// function does not. For it to access the global variable, '$condition',)
+ comment(// it must be declared 'global')
+ ident(run_check)operator(()operator(\))operator(;)
+
+ pre_type(global) local_variable($condition)operator(;)
+
+ comment(// 'run_check' will have updated, '$condition', and since it has been)
+ comment(// declared 'global' here, it is accessable)
+
+ reserved(if) operator(()local_variable($condition)operator(\))
+ operator({)
+ operator(;) comment(// ...)
+ operator(})
+operator(})
+
+comment(// @@PLEAC@@_10.3)
+comment(// Local scopes are not created in the same way as in Perl [by simply enclosing)
+comment(// within braces]: only via the creation of functions are local scopes created)
+
+comment(// Doesn't create a local scope; '$myvariable' is created at top-level)
+operator({)
+ local_variable($myvariable) operator(=) integer(7)operator(;)
+operator(})
+
+comment(// '$myvariable' is accessable here)
+pre_type(echo) local_variable($myvariable) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// ------------)
+
+operator({)
+ local_variable($counter) operator(=) integer(0)operator(;)
+
+ comment(// Local scope created within function, but not within surrounding braces)
+ comment(// so:)
+ comment(// * '$counter' is actually a top-level variable, so globally accessable)
+ comment(// * 'next_counter' has no implict access to '$counter'; must be granted)
+ comment(// via 'global' keyword)
+
+ pre_type(function) ident(next_counter)operator(()operator(\)) operator({) pre_type(global) local_variable($counter)operator(;) local_variable($counter)operator(++)operator(;) operator(})
+operator(})
+
+comment(// ----------------------------)
+
+comment(// PHP doesn't, AFAIK, offer an equivalent to Perl's BEGIN block. Similar)
+comment(// behaviour may be obtained by defining a class, and including such code)
+comment(// in its constructor)
+
+pre_type(class) constant(BEGIN)
+operator({)
+ pre_type(private) local_variable($myvariable)operator(;)
+
+ pre_type(function) ident(__construct)operator(()operator(\))
+ operator({)
+ local_variable($this)operator(->)ident(myvariable) operator(=) integer(5)operator(;)
+ operator(})
+
+ pre_type(function) ident(othersub)operator(()operator(\))
+ operator({)
+ pre_type(echo) local_variable($this)operator(->)ident(myvariable) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+ operator(})
+operator(})
+
+comment(// ------------)
+
+local_variable($b) operator(=) pre_type(new) constant(BEGIN)operator(()operator(\))operator(;)
+
+local_variable($b)operator(->)ident(othersub)operator(()operator(\))operator(;)
+
+comment(// ----------------------------)
+
+comment(// PHP, like C, supports 'static' local variables, that is, those that upon)
+comment(// first access are initialised, and thence retain their value between function)
+comment(// calls. However, the 'counter' example is better implemented as a class)
+
+pre_type(class) constant(Counter)
+operator({)
+ pre_type(private) local_variable($counter)operator(;)
+
+ pre_type(function) ident(__construct)operator(()local_variable($counter_init)operator(\))
+ operator({)
+ local_variable($this)operator(->)ident(counter) operator(=) local_variable($counter_init)operator(;)
+ operator(})
+
+ pre_type(function) ident(next_counter)operator(()operator(\)) operator({) local_variable($this)operator(->)ident(counter)operator(++)operator(;) reserved(return) local_variable($this)operator(->)ident(counter)operator(;) operator(})
+ pre_type(function) ident(prev_counter)operator(()operator(\)) operator({) local_variable($this)operator(->)ident(counter)operator(;) reserved(return) local_variable($this)operator(->)ident(counter)operator(;) operator(})
+operator(})
+
+comment(// ------------)
+
+local_variable($counter) operator(=) pre_type(new) constant(Counter)operator(()integer(42)operator(\))operator(;)
+pre_type(echo) local_variable($counter)operator(->)ident(next_counter)operator(()operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+pre_type(echo) local_variable($counter)operator(->)ident(next_counter)operator(()operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+pre_type(echo) local_variable($counter)operator(->)ident(prev_counter)operator(()operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// @@PLEAC@@_10.4)
+comment(// AFAICT there is no means of obtaining the name of the currently executing)
+comment(// function, or, for that matter, perform any stack / activation record,)
+comment(// inspection. It *is* possible to:)
+comment(//)
+comment(// * Obtain a list of the currently-defined functions ['get_defined_functions'])
+comment(// * Check whether a specific function exists ['function_exists'])
+comment(// * Use the 'Reflection API')
+comment(//)
+comment(// So, to solve this problem would seem to require adopting a convention where)
+comment(// a string representing the function name is passed as an argument, or a local)
+comment(// variable [perhaps called, '$name'] is so set [contrived, and of limited use])
+
+pre_type(function) ident(whoami)operator(()operator(\))
+operator({)
+ local_variable($name) operator(=) delimiter(')string(whoami)delimiter(')operator(;)
+ pre_type(echo) delimiter(")string(I am: )operator({)local_variable($name)operator(})char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// ------------)
+
+ident(whoami)operator(()operator(\))operator(;)
+
+comment(// @@PLEAC@@_10.5)
+comment(// In PHP all items exist as 'memory references' [i.e. non-modifiable pointers],)
+comment(// so when passing an item as a function argument, or returning an item from)
+comment(// a function, it is this 'memory reference' that is passed, and *not* the)
+comment(// contents of that item. Should several references to an item exist [e.g. if)
+comment(// passed to a function then at least two such references would exist in)
+comment(// different scopes] they would all be refering to the same copy of the item.)
+comment(// However, if an attempt is made to alter the item is made, a copy is made)
+comment(// and it is the copy that is altered, leaving the original intact.)
+comment(// )
+comment(// The PHP reference mechanism is used to selectively prevent this behaviour,)
+comment(// and ensure that if a change is made to an item that no copy is made, and that)
+comment(// it is the original item that is changed. Importantly, there is no efficiency)
+comment(// gain from passing function parameters using references if the parameter item)
+comment(// is not altered.)
+
+comment(// A copy of the item referred to by, '$arr', is made, and altered; original)
+comment(// remains intact)
+pre_type(function) ident(array_by_value)operator(()local_variable($arr)operator(\))
+operator({)
+ local_variable($arr)operator([)integer(0)operator(]) operator(=) integer(7)operator(;)
+ pre_type(echo) local_variable($arr)operator([)integer(0)operator(]) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// No copy is made; original item referred to by, '$arr', is altered)
+pre_type(function) ident(array_by_ref)operator(()operator(&)local_variable($arr)operator(\))
+operator({)
+ local_variable($arr)operator([)integer(0)operator(]) operator(=) integer(7)operator(;)
+ pre_type(echo) local_variable($arr)operator([)integer(0)operator(]) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// ------------)
+
+local_variable($arr) operator(=) pre_type(array)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(\))operator(;)
+
+pre_type(echo) local_variable($arr)operator([)integer(0)operator(]) operator(.) delimiter(")char(\\n)delimiter(")operator(;) comment(// output: 1 )
+ident(array_by_value)operator(()local_variable($arr)operator(\))operator(;) comment(// output: 7)
+pre_type(echo) local_variable($arr)operator([)integer(0)operator(]) operator(.) delimiter(")char(\\n)delimiter(")operator(;) comment(// output: 1 )
+
+local_variable($arr) operator(=) pre_type(array)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(\))operator(;)
+
+pre_type(echo) local_variable($arr)operator([)integer(0)operator(]) operator(.) delimiter(")char(\\n)delimiter(")operator(;) comment(// output: 1 )
+ident(array_by_ref)operator(()local_variable($arr)operator(\))operator(;) comment(// output: 7)
+pre_type(echo) local_variable($arr)operator([)integer(0)operator(]) operator(.) delimiter(")char(\\n)delimiter(")operator(;) comment(// output: 7 )
+
+comment(// ----------------------------)
+
+comment(// Since, 'add_vecpair', does not attempt to alter either, '$x' or '$y', it makes)
+comment(// no difference whether they are 'passed by value', or 'passed by reference')
+pre_type(function) ident(add_vecpair)operator(()local_variable($x)operator(,) local_variable($y)operator(\))
+operator({)
+ local_variable($r) operator(=) pre_type(array)operator(()operator(\))operator(;)
+ local_variable($length) operator(=) ident(count)operator(()local_variable($x)operator(\))operator(;)
+ reserved(for)operator(()local_variable($i) operator(=) integer(0)operator(;) local_variable($i) operator(<) local_variable($length)operator(;) local_variable($i)operator(++)operator(\)) local_variable($r)operator([)local_variable($i)operator(]) operator(=) local_variable($x)operator([)local_variable($i)operator(]) operator(+) local_variable($y)operator([)local_variable($i)operator(])operator(;)
+ reserved(return) local_variable($r)operator(;)
+operator(})
+
+comment(// ...)
+ident(count)operator(()local_variable($arr1)operator(\)) operator(==) ident(count)operator(()local_variable($arr2)operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(usage: add_vecpair ARR1 ARR2)char(\\n)delimiter(")operator(\))operator(;)
+
+comment(// 'passed by value')
+local_variable($arr3) operator(=) ident(add_vecpair)operator(()local_variable($arr1)operator(,) local_variable($arr2)operator(\))operator(;)
+
+comment(// 'passed by reference' [also possible to override default 'passed by value')
+comment(// if required])
+local_variable($arr3) operator(=) ident(add_vecpair)operator(()operator(&)local_variable($arr1)operator(,) operator(&)local_variable($arr2)operator(\))operator(;)
+
+comment(// @@PLEAC@@_10.6)
+comment(// PHP can be described as a dynamically typed language because variables serve)
+comment(// as identifiers, and the same variable may refer to data of various types.)
+comment(// As such, the set of arguments passed to a function may vary in type between)
+comment(// calls, as can the type of return value. Where this is likely to occur type)
+comment(// checking should be performed either / both within the function body, and)
+comment(// when obtaining it's return value. As for Perl-style 'return context', I)
+comment(// don't believe it is supported by PHP)
+
+comment(// Can return any type)
+pre_type(function) ident(mysub)operator(()operator(\))
+operator({)
+ comment(// ...)
+ reserved(return) integer(5)operator(;)
+ comment(// ...)
+ reserved(return) pre_type(array)operator(()integer(5)operator(\))operator(;)
+ comment(// ...)
+ reserved(return) delimiter(')string(5)delimiter(')operator(;)
+operator(})
+
+comment(// Throw away return type [i.e. returns a 'void' type ?])
+ident(mysub)operator(()operator(\))operator(;)
+
+comment(// Check return type. Can do via:)
+comment(// * gettype($var\))
+comment(// * is_xxx e.g. is_array($var\), is_muneric($var\), ...)
+local_variable($ret) operator(=) ident(mysub)operator(()operator(\))operator(;)
+
+reserved(if) operator(()ident(is_numeric)operator(()local_variable($ret)operator(\))operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+reserved(if) operator(()ident(is_array)operator(()local_variable($ret)operator(\))operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+reserved(if) operator(()ident(is_string)operator(()local_variable($ret)operator(\))operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+comment(// @@PLEAC@@_10.7)
+comment(// PHP doesn't directly support named / keyword parameters, but these can be)
+comment(// easily mimiced using a class of key / value pairs, and passing a variable)
+comment(// number of arguments)
+
+pre_type(class) constant(KeyedValue)
+operator({)
+ pre_type(public) local_variable($key)operator(,) local_variable($value)operator(;)
+ pre_type(public) pre_type(function) ident(__construct)operator(()local_variable($key)operator(,) local_variable($value)operator(\)) operator({) local_variable($this)operator(->)ident(key) operator(=) local_variable($key)operator(;) local_variable($this)operator(->)ident(value) operator(=) local_variable($value)operator(;) operator(})
+operator(})
+
+pre_type(function) ident(the_func)operator(()operator(\))
+operator({)
+ reserved(foreach) operator(()ident(func_get_args)operator(()operator(\)) reserved(as) local_variable($arg)operator(\))
+ operator({)
+ ident(printf)operator(()delimiter(")string(Key: %10s|Value:%10s)char(\\n)delimiter(")operator(,) local_variable($arg)operator(->)ident(key)operator(,) local_variable($arg)operator(->)ident(value)operator(\))operator(;)
+ operator(})
+operator(})
+
+comment(// ----)
+
+ident(the_func)operator(()pre_type(new) constant(KeyedValue)operator(()delimiter(')string(name)delimiter(')operator(,) delimiter(')string(Bob)delimiter(')operator(\))operator(,)
+ pre_type(new) constant(KeyedValue)operator(()delimiter(')string(age)delimiter(')operator(,) integer(36)operator(\))operator(,)
+ pre_type(new) constant(KeyedValue)operator(()delimiter(')string(income)delimiter(')operator(,) integer(51000)operator(\))operator(\))operator(;)
+
+comment(// ----------------------------)
+
+comment(// Alternatively, an associative array of key / value pairs may be constructed.)
+comment(// With the aid of the 'extract' built-in function, the key part of this array)
+comment(// may be intsntiated to a variable name, thus more closely approximating the)
+comment(// behaviour of true named parameters)
+
+pre_type(function) ident(the_func)operator(()local_variable($var_array)operator(\))
+operator({)
+ ident(extract)operator(()local_variable($var_array)operator(\))operator(;)
+
+ reserved(if) operator(()pre_type(isset)operator(()local_variable($name)operator(\))operator(\)) ident(printf)operator(()delimiter(")string(Name: %s)char(\\n)delimiter(")operator(,) local_variable($name)operator(\))operator(;)
+ reserved(if) operator(()pre_type(isset)operator(()local_variable($age)operator(\))operator(\)) ident(printf)operator(()delimiter(")string(Age: %s)char(\\n)delimiter(")operator(,) local_variable($age)operator(\))operator(;)
+ reserved(if) operator(()pre_type(isset)operator(()local_variable($income)operator(\))operator(\)) ident(printf)operator(()delimiter(")string(Income: %s)char(\\n)delimiter(")operator(,) local_variable($income)operator(\))operator(;)
+operator(})
+
+comment(// ----)
+
+ident(the_func)operator(()pre_type(array)operator(()delimiter(')string(name)delimiter(') operator(=>) delimiter(')string(Bob)delimiter(')operator(,) delimiter(')string(age)delimiter(') operator(=>) integer(36)operator(,) delimiter(')string(income)delimiter(') operator(=>) integer(51000)operator(\))operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(class) constant(RaceTime)
+operator({)
+ pre_type(public) local_variable($time)operator(,) local_variable($dim)operator(;)
+ pre_type(public) pre_type(function) ident(__construct)operator(()local_variable($time)operator(,) local_variable($dim)operator(\)) operator({) local_variable($this)operator(->)ident(time) operator(=) local_variable($time)operator(;) local_variable($this)operator(->)ident(dim) operator(=) local_variable($dim)operator(;) operator(})
+operator(})
+
+pre_type(function) ident(the_func)operator(()local_variable($var_array)operator(\))
+operator({)
+ ident(extract)operator(()local_variable($var_array)operator(\))operator(;)
+
+ reserved(if) operator(()pre_type(isset)operator(()local_variable($start_time)operator(\))operator(\)) ident(printf)operator(()delimiter(")string(start: %d - %s)char(\\n)delimiter(")operator(,) local_variable($start_time)operator(->)ident(time)operator(,) local_variable($start_time)operator(->)ident(dim)operator(\))operator(;)
+ reserved(if) operator(()pre_type(isset)operator(()local_variable($finish_time)operator(\))operator(\)) ident(printf)operator(()delimiter(")string(finish: %d - %s)char(\\n)delimiter(")operator(,) local_variable($finish_time)operator(->)ident(time)operator(,) local_variable($finish_time)operator(->)ident(dim)operator(\))operator(;)
+ reserved(if) operator(()pre_type(isset)operator(()local_variable($incr_time)operator(\))operator(\)) ident(printf)operator(()delimiter(")string(incr: %d - %s)char(\\n)delimiter(")operator(,) local_variable($incr_time)operator(->)ident(time)operator(,) local_variable($incr_time)operator(->)ident(dim)operator(\))operator(;)
+operator(})
+
+comment(// ----)
+
+ident(the_func)operator(()pre_type(array)operator(()delimiter(')string(start_time)delimiter(') operator(=>) pre_type(new) constant(RaceTime)operator(()integer(20)operator(,) delimiter(')string(s)delimiter(')operator(\))operator(,)
+ delimiter(')string(finish_time)delimiter(') operator(=>) pre_type(new) constant(RaceTime)operator(()integer(5)operator(,) delimiter(')string(m)delimiter(')operator(\))operator(,)
+ delimiter(')string(incr_time)delimiter(') operator(=>) pre_type(new) constant(RaceTime)operator(()integer(3)operator(,) delimiter(')string(m)delimiter(')operator(\))operator(\))operator(\))operator(;)
+
+ident(the_func)operator(()pre_type(array)operator(()delimiter(')string(start_time)delimiter(') operator(=>) pre_type(new) constant(RaceTime)operator(()integer(5)operator(,) delimiter(')string(m)delimiter(')operator(\))operator(,)
+ delimiter(')string(finish_time)delimiter(') operator(=>) pre_type(new) constant(RaceTime)operator(()integer(30)operator(,) delimiter(')string(m)delimiter(')operator(\))operator(\))operator(\))operator(;)
+
+ident(the_func)operator(()pre_type(array)operator(()delimiter(')string(start_time)delimiter(') operator(=>) pre_type(new) constant(RaceTime)operator(()integer(30)operator(,) delimiter(')string(m)delimiter(')operator(\))operator(\))operator(\))operator(;)
+
+comment(// @@PLEAC@@_10.8)
+comment(// The 'list' keyword [looks like a function but is actually a special language)
+comment(// construct] may be used to perform multiple assignments from a numerically)
+comment(// indexed array of values, and offers the added bonus of being able to skip)
+comment(// assignment of one, or more, of those values)
+
+pre_type(function) ident(func)operator(()operator(\)) operator({) reserved(return) pre_type(array)operator(()integer(3)operator(,) integer(6)operator(,) integer(9)operator(\))operator(;) operator(})
+
+comment(// ------------)
+
+pre_type(list)operator(()local_variable($a)operator(,) local_variable($b)operator(,) local_variable($c)operator(\)) operator(=) pre_type(array)operator(()integer(6)operator(,) integer(7)operator(,) integer(8)operator(\))operator(;)
+
+comment(// Provided 'func' returns an numerically-indexed array, the following)
+comment(// multiple assignment will work)
+pre_type(list)operator(()local_variable($a)operator(,) local_variable($b)operator(,) local_variable($c)operator(\)) operator(=) ident(func)operator(()operator(\))operator(;)
+
+comment(// Any existing variables no longer wanted would need to be 'unset')
+pre_type(unset)operator(()local_variable($b)operator(\))operator(;)
+
+comment(// As above, but second element of return array discarded)
+pre_type(list)operator(()local_variable($a)operator(,)operator(,)local_variable($c)operator(\)) operator(=) ident(func)operator(()operator(\))operator(;)
+
+comment(// ----------------------------)
+
+comment(// Care needed to ensure returned array is numerically-indexed)
+pre_type(list)operator(()local_variable($dev)operator(,) local_variable($ino)operator(,)operator(,)operator(,)local_variable($uid)operator(\)) operator(=) ident(array_slice)operator(()ident(array_values)operator(()ident(stat)operator(()local_variable($filename)operator(\))operator(\))operator(,) integer(0)operator(,) integer(13)operator(\))operator(;)
+
+comment(// @@PLEAC@@_10.9)
+comment(// Multiple return values are possible via packing a set of values within a)
+comment(// numerically-indexed array and using 'list' to extract them)
+
+pre_type(function) ident(some_func)operator(()operator(\)) operator({) reserved(return) pre_type(array)operator(()pre_type(array)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(\))operator(,) pre_type(array)operator(()delimiter(')string(a)delimiter(') operator(=>) integer(1)operator(,) delimiter(')string(b)delimiter(') operator(=>) integer(2)operator(\))operator(\))operator(;) operator(})
+
+comment(// ------------)
+
+pre_type(list)operator(()local_variable($arr)operator(,) local_variable($hash)operator(\)) operator(=) ident(some_func)operator(()operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(some_func)operator(()operator(&)local_variable($arr)operator(,) operator(&)local_variable($hash)operator(\)) operator({) reserved(return) pre_type(array)operator(()local_variable($arr)operator(,) local_variable($hash)operator(\))operator(;) operator(})
+
+comment(// ------------)
+
+local_variable($arrin) operator(=) pre_type(array)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(\))operator(;) local_variable($hashin) operator(=) pre_type(array)operator(()delimiter(')string(a)delimiter(') operator(=>) integer(1)operator(,) delimiter(')string(b)delimiter(') operator(=>) integer(2)operator(\))operator(;)
+
+pre_type(list)operator(()local_variable($arr)operator(,) local_variable($hash)operator(\)) operator(=) ident(some_func)operator(()local_variable($arrin)operator(,) local_variable($hashin)operator(\))operator(;)
+
+comment(// @@PLEAC@@_10.10)
+comment(// AFAICT, most of the PHP library functions are designed to return some required )
+comment(// value on success, and FALSE on exit. Whilst it is possible to return NULL, or)
+comment(// one of the recognised 'empty' values [e.g. '' or 0 or an empty array etc],)
+comment(// FALSE actually seems to be the preferred means of indicating failure)
+
+pre_type(function) ident(a_func)operator(()operator(\)) operator({) reserved(return) constant(FALSE)operator(;) operator(})
+
+ident(a_func)operator(()operator(\)) operator(|)operator(|) reserved(die)operator(()delimiter(")string(Function failed)char(\\n)delimiter(")operator(\))operator(;)
+
+reserved(if) operator(()operator(!)ident(a_func)operator(()operator(\))operator(\)) reserved(die)operator(()delimiter(")string(Function failed)char(\\n)delimiter(")operator(\))operator(;)
+
+comment(// @@PLEAC@@_10.11)
+comment(// Whether PHP is seen to support prototyping depends on the accepted)
+comment(// definition of this term:)
+comment(//)
+comment(// * Prototyping along the lines used in Ada, Modula X, and even C / C++,)
+comment(// in which a function's interface is declared separately from its)
+comment(// implementation, is *not* supported)
+comment(//)
+comment(// * Prototyping in which, as part of the function definition, parameter)
+comment(// information must be supplied. In PHP a function definition neither)
+comment(// parameter, nor return type, information needs to be supplied, though)
+comment(// it is usual to see a parameter list supplied [indicates the number,)
+comment(// positional order, and optionally, whether a parameter is passed by)
+comment(// reference; no type information is present]. In short, prototyping in)
+comment(// PHP is optional, and limited)
+
+pre_type(function) ident(func_with_one_arg)operator(()local_variable($arg1)operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+pre_type(function) ident(func_with_two_arg)operator(()local_variable($arg1)operator(,) local_variable($arg2)operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+pre_type(function) ident(func_with_three_arg)operator(()local_variable($arg1)operator(,) local_variable($arg2)operator(,) local_variable($arg3)operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+comment(// The following may be interpreted as meaning a function accepting no)
+comment(// arguments:)
+pre_type(function) ident(func_with_no_arg)operator(()operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+comment(// whilst the following may mean a function taking zero or more arguments)
+pre_type(function) ident(func_with_no_arg_information)operator(()operator(\))
+operator({)
+ operator(;) comment(// ...)
+operator(})
+
+comment(// @@PLEAC@@_10.12)
+comment(// Unlike in Perl, PHP's 'die' [actually an alias for 'exit'] doesn't throw)
+comment(// an exception, but instead terminates the script, optionally either)
+comment(// returning an integer value to the operating system, or printing a message.)
+comment(// So, the following, does not exhibit the same behaviour as the Perl example)
+
+reserved(die)operator(()delimiter(")string(some message)char(\\n)delimiter(")operator(\))operator(;)
+
+comment(// Instead, like so many modern languages, PHP implements exception handling)
+comment(// via the 'catch' and 'throw' keywords. Furthermore, a C++ or Java programmer)
+comment(// would find PHP's exception handling facility remarkably similar to those)
+comment(// of their respective languages. A simple, canonical example follows:)
+
+comment(// Usual to derive new exception classes from the built-in, 'Exception',)
+comment(// class)
+pre_type(class) constant(MyException) pre_type(extends) constant(Exception)
+operator({)
+ comment(// ...)
+operator(})
+
+comment(// ...)
+
+reserved(try)
+operator({)
+ comment(// ...)
+ reserved(if) operator(()local_variable($some_problem_detected)operator(\)) reserved(throw) pre_type(new) constant(MyException)operator(()delimiter(')string(some message)delimiter(')operator(,) local_variable($some_error_code)operator(\))operator(;)
+ comment(// ..)
+operator(})
+
+reserved(catch) operator(()constant(MyException) local_variable($e)operator(\))
+operator({)
+ operator(;) comment(// ... handle the problem ...)
+operator(})
+
+comment(// ----------------------------)
+
+pre_type(class) constant(FullMoonException) pre_type(extends) constant(Exception)
+operator({)
+ comment(// ...)
+operator(})
+
+comment(// ...)
+
+reserved(try)
+operator({)
+ comment(// ...)
+ reserved(if) operator(()local_variable($some_problem_detected)operator(\)) reserved(throw) pre_type(new) constant(FullMoonException)operator(()delimiter(')string(...)delimiter(')operator(,) local_variable($full_moon_error_code)operator(\))operator(;)
+ comment(// ..)
+operator(})
+
+reserved(catch) operator(()constant(FullMoonException) local_variable($e)operator(\))
+operator({)
+ comment(// ... rethrow the exception - will propagate to higher level ...)
+ reserved(throw) local_variable($e)operator(;)
+operator(})
+
+comment(// @@PLEAC@@_10.13)
+comment(// Please refer to discussion about PHP scope in section two of this chapter.)
+comment(// Briefly, PHP assumes a variable name within a function to be local unless)
+comment(// it has been specifically declared with the, 'global', keyword, in which)
+comment(// case it refers to a variable in the 'superglobal' array, '$GLOBALS'. Thus,)
+comment(// inadvertant variable name shadowing cannot occur since it is it not possible )
+comment(// to use the same name to refer to both a local and a global variable. If)
+comment(// accessing a global variable care should be taken to not accidentally update)
+comment(// it. The techniques used in this section are simply not required.)
+
+comment(// *** NOT TRANSLATED ***)
+
+comment(// @@PLEAC@@_10.14)
+comment(// In PHP once a function has been defined it remains defined. In other words,)
+comment(// it cannot be undefined / deleted, nor can that particular function name be)
+comment(// reused to reference another function body. Even the lambda-like functions)
+comment(// created via the 'create_function' built-in, cannot be undefined [they exist)
+comment(// until script termination, thus creating too many of these can actually)
+comment(// exhaust memory !]. However, since the latter can be assigned to variables,)
+comment(// the same variable name can be used to reference difference functions [and)
+comment(// when this is done the reference to the previous function is lost (unless)
+comment(// deliberately saved\), though the function itself continues to exist].)
+comment(//)
+comment(// If, however, all that is needed is a simple function aliasing facility,)
+comment(// then just assign the function name to a variable, and execute using the)
+comment(// variable name)
+
+comment(// Original function)
+pre_type(function) ident(expand)operator(()operator(\)) operator({) pre_type(echo) delimiter(")string(expand)char(\\n)delimiter(")operator(;) operator(})
+
+comment(// Prove that function exists)
+pre_type(echo) operator(()ident(function_exists)operator(()delimiter(')string(expand)delimiter(')operator(\)) operator(?) delimiter(')string(yes)delimiter(') operator(:) delimiter(')string(no)delimiter(')operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// Use a variable to alias it)
+local_variable($grow) operator(=) delimiter(')string(expand)delimiter(')operator(;)
+
+comment(// Call function via original name, and variable, respectively)
+ident(expand)operator(()operator(\))operator(;)
+
+local_variable($grow)operator(()operator(\))operator(;)
+
+comment(// Remove alias variable)
+pre_type(unset)operator(()local_variable($grow)operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(fred)operator(()operator(\)) operator({) pre_type(echo) delimiter(")string(fred)char(\\n)delimiter(")operator(;) operator(})
+
+local_variable($barney) operator(=) delimiter(')string(fred)delimiter(')operator(;)
+
+local_variable($barney)operator(()operator(\))operator(;)
+
+pre_type(unset)operator(()local_variable($barney)operator(\))operator(;)
+
+ident(fred)operator(()operator(\))operator(;)
+
+comment(// ------------)
+
+local_variable($fred) operator(=) ident(create_function)operator(()delimiter(')delimiter(')operator(,) delimiter(')string(echo "fred)string(\\)string(n";)delimiter(')operator(\))operator(;)
+
+local_variable($barney) operator(=) local_variable($fred)operator(;)
+
+local_variable($barney)operator(()operator(\))operator(;)
+
+pre_type(unset)operator(()local_variable($barney)operator(\))operator(;)
+
+local_variable($fred)operator(()operator(\))operator(;)
+
+comment(// ----------------------------)
+
+pre_type(function) ident(red)operator(()local_variable($text)operator(\)) operator({) reserved(return) delimiter(")string(<FONT COLOR='red'>)local_variable($text)string(</FONT>)delimiter(")operator(;) operator(})
+
+pre_type(echo) ident(red)operator(()delimiter(')string(careful here)delimiter(')operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+comment(// ------------)
+
+local_variable($colour) operator(=) delimiter(')string(red)delimiter(')operator(;)
+
+error($)local_variable($colour) operator(=) ident(create_function)operator(()delimiter(')string($text)delimiter(')operator(,) delimiter(')string(global $colour;)
+string(return "<FONT COLOR=)char(\\')string($colour)char(\\')string(>$text</FONT>";)delimiter(')operator(\))operator(;)
+
+pre_type(echo) error($)local_variable($colour)operator(()delimiter(')string(careful here)delimiter(')operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+
+pre_type(unset)operator(()error($)local_variable($colour)operator(\))operator(;)
+
+comment(// ----)
+
+local_variable($colours) operator(=) ident(split)operator(()delimiter(')string( )delimiter(')operator(,) delimiter(')string(red blue green yellow orange purple violet)delimiter(')operator(\))operator(;)
+
+reserved(foreach) operator(()local_variable($colours) reserved(as) local_variable($colour)operator(\))
+operator({)
+ error($)local_variable($colour) operator(=) ident(create_function)operator(()delimiter(')string($text)delimiter(')operator(,) delimiter(')string(global $colour;)
+ string(return "<FONT COLOR=)char(\\')string($colour)char(\\')string(>$text</FONT>";)delimiter(')operator(\))operator(;)
+operator(})
+
+reserved(foreach) operator(()local_variable($colours) reserved(as) local_variable($colour)operator(\)) operator({) pre_type(echo) error($)local_variable($colour)operator(()delimiter(")string(Careful with this )local_variable($colour)string(, James)delimiter(")operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;) operator(})
+
+reserved(foreach) operator(()local_variable($colours) reserved(as) local_variable($colour)operator(\)) operator({) pre_type(unset)operator(()error($)local_variable($colour)operator(\))operator(;) operator(})
+
+comment(// @@PLEAC@@_10.15)
+comment(// PHP sports an AUTOLOAD facility that is quite easy to use, but, AFAICT, is geared)
+comment(// towards the detection of unavailable classes rather than for individual functions.)
+comment(// Here is a rudimentary example:)
+
+pre_type(function) ident(__autoload)operator(()local_variable($classname)operator(\))
+operator({)
+ reserved(if) operator(()operator(!)ident(file_exists)operator(()local_variable($classname)operator(\))operator(\))
+ operator({)
+ comment(// Class file does not exist, so handle situation; in this case,)
+ comment(// issue error message, and exit program)
+ reserved(die)operator(()delimiter(")string(File for class: )operator({)local_variable($classname)operator(})string( not found - aborting)char(\\n)delimiter(")operator(\))operator(;)
+ operator(})
+ reserved(else)
+ operator({)
+ comment(// Class file exists, so load it)
+ pre_type(require_once) local_variable($classname)operator(;)
+ operator(})
+operator(})
+
+comment(// ------------)
+
+comment(// Attempt to instantiate object of undefined class )
+pre_type(new) constant(UnknownClassObject)operator(()operator(\))operator(;)
+
+comment(// Execution continues here if class exists)
+comment(// ...)
+
+comment(// ----------------------------)
+
+comment(// It is also possible to perform [quite extensive] introspection on functions,)
+comment(// variables etc, so it is possible to check whether a function exists before)
+comment(// executing it, thus allowing a non-existent functions to be searched for and)
+comment(// loaded from a source file, or perhaps dynamically defined. An example of what)
+comment(// could be described as a custom autoload facility appears below.)
+
+local_variable($colours) operator(=) pre_type(array)operator(()delimiter(')string(red)delimiter(')operator(,) delimiter(')string(blue)delimiter(')operator(,) delimiter(')string(green)delimiter(')operator(,) delimiter(')string(yellow)delimiter(')operator(,) delimiter(')string(orange)delimiter(')operator(,) delimiter(')string(purple)delimiter(')operator(,) delimiter(')string(violet)delimiter(')operator(\))operator(;)
+
+reserved(foreach) operator(()local_variable($colours) reserved(as) local_variable($colour)operator(\))
+operator({)
+ error($)local_variable($colour) operator(=) ident(create_function)operator(()delimiter(')string($text)delimiter(')operator(,) delimiter(')string(global $colour;)
+ string(return "<FONT COLOR=)char(\\')string($colour)char(\\')string(>$text</FONT>";)delimiter(')operator(\))operator(;)
+operator(})
+
+comment(// Let's add a new colour to the list)
+ident(array_push)operator(()local_variable($colours)operator(,) delimiter(')string(chartreuse)delimiter(')operator(\))operator(;)
+
+reserved(foreach) operator(()local_variable($colours) reserved(as) local_variable($colour)operator(\))
+operator({)
+ comment(// Checking whether function is defined)
+ reserved(if) operator(()operator(!)ident(function_exists)operator(()error($)local_variable($colour)operator(\))operator(\))
+ operator({)
+ comment(// Doesn't exist, so dynamically define it)
+ error($)local_variable($colour) operator(=) ident(create_function)operator(()delimiter(')string($text)delimiter(')operator(,) delimiter(')string(global $colour;)
+ string(return "<FONT COLOR=)char(\\')string($colour)char(\\')string(>$text</FONT>";)delimiter(')operator(\))operator(;)
+
+ comment(// Alternatively, if it exists in a source file, 'include' the file:)
+ comment(// include 'newcolours.php')
+ operator(})
+
+ pre_type(echo) error($)local_variable($colour)operator(()delimiter(")string(Careful with this )local_variable($colour)string(, James)delimiter(")operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+operator(})
+
+reserved(foreach) operator(()local_variable($colours) reserved(as) local_variable($colour)operator(\)) pre_type(unset)operator(()error($)local_variable($colour)operator(\))operator(;)
+
+comment(// @@PLEAC@@_10.16)
+comment(// *** Warning *** Whilst PHP *does* allow functions to be defined within other)
+comment(// functions it needs to be clearly understood that these 'inner' functions:)
+comment(// * Do not exist until the outer function is called a first time, at which time)
+comment(// they then remain defined)
+comment(// * Are global in scope, so are accessable outside the function by their name;)
+comment(// the fact that they are nested within another function has, AFAICT, no bearing)
+comment(// on name resolution)
+comment(// * Do not form a closure: the inner function is merely 'parked' within the)
+comment(// outer function, and has no implicit access to the outer function's variables)
+comment(// or other inner functions)
+
+pre_type(function) ident(outer)operator(()local_variable($arg)operator(\))
+operator({)
+ local_variable($x) operator(=) local_variable($arg) operator(+) integer(35)operator(;)
+ pre_type(function) ident(inner)operator(()operator(\)) operator({) reserved(return) local_variable($x) operator(*) integer(19)operator(;) operator(})
+
+ comment(// *** wrong *** 'inner' returns 0 * 19, not ($arg + 35\) * 19)
+ reserved(return) local_variable($x) operator(+) ident(inner)operator(()operator(\))operator(;)
+operator(})
+
+comment(// ----------------------------)
+
+pre_type(function) ident(outer)operator(()local_variable($arg)operator(\))
+operator({)
+ local_variable($x) operator(=) local_variable($arg) operator(+) integer(35)operator(;)
+
+ comment(// No implicit access to outer function scope; any required data must be)
+ comment(// explicity passed)
+ pre_type(function) ident(inner)operator(()local_variable($x)operator(\)) operator({) reserved(return) local_variable($x) operator(*) integer(19)operator(;) operator(})
+
+ reserved(return) local_variable($x) operator(+) ident(inner)operator(()local_variable($x)operator(\))operator(;)
+operator(})
+
+comment(// ------------ )
+
+comment(// Equivalent to previously-shown code)
+pre_type(function) ident(inner)operator(()local_variable($x)operator(\))
+operator({)
+ reserved(return) local_variable($x) operator(*) integer(19)operator(;)
+operator(})
+
+pre_type(function) ident(outer)operator(()local_variable($arg)operator(\))
+operator({)
+ local_variable($x) operator(=) local_variable($arg) operator(+) integer(35)operator(;)
+ reserved(return) local_variable($x) operator(+) ident(inner)operator(()local_variable($x)operator(\))operator(;)
+operator(})
+
+comment(// @@PLEAC@@_10.17)
+comment(// @@INCOMPLETE@@)
+comment(// @@INCOMPLETE@@)
+
+comment(// @@PLEAC@@_16.1)
+comment(// Run a command and return its results as a string.)
+local_variable($output_string) operator(=) ident(shell_exec)operator(()delimiter(')string(program args)delimiter(')operator(\))operator(;)
+
+comment(// Same as above, using backtick operator.)
+local_variable($output_string) operator(=) error(`)ident(program) ident(args)error(`)operator(;)
+
+comment(// Run a command and return its results as a list of strings,)
+comment(// one per line.)
+local_variable($output_lines) operator(=) pre_type(array)operator(()operator(\))operator(;)
+ident(exec)operator(()delimiter(')string(program args)delimiter(')operator(,) local_variable($output_lines)operator(\))operator(;)
+
+comment(// -----------------------------)
+
+comment(// The only way to execute a program without using the shell is to)
+comment(// use pcntl_exec(\). However, there is no way to do redirection, so)
+comment(// you can't capture its output.)
+
+local_variable($pid) operator(=) ident(pcntl_fork)operator(()operator(\))operator(;)
+reserved(if) operator(()local_variable($pid) operator(==) integer(-1)operator(\)) operator({)
+ reserved(die)operator(()delimiter(')string(cannot fork)delimiter(')operator(\))operator(;)
+operator(}) reserved(elseif) operator(()local_variable($pid)operator(\)) operator({)
+ ident(pcntl_waitpid)operator(()local_variable($pid)operator(,) local_variable($status)operator(\))operator(;)
+operator(}) reserved(else) operator({)
+ comment(// Note that pcntl_exec(\) automatically prepends the program name)
+ comment(// to the array of arguments; the program name cannot be spoofed.)
+ ident(pcntl_exec)operator(()local_variable($program)operator(,) pre_type(array)operator(()local_variable($arg1)operator(,) local_variable($arg2)operator(\))operator(\))operator(;)
+operator(})
+
+comment(// @@PLEAC@@_16.2)
+comment(// Run a simple command and retrieve its result code.)
+ident(exec)operator(()delimiter(")string(vi )local_variable($myfile)delimiter(")operator(,) local_variable($output)operator(,) local_variable($result_code)operator(\))operator(;)
+
+comment(// -----------------------------)
+
+comment(// Use the shell to perform redirection.)
+ident(exec)operator(()delimiter(')string(cmd1 args | cmd2 | cmd3 >outfile)delimiter(')operator(\))operator(;)
+ident(exec)operator(()delimiter(')string(cmd args <infile >outfile 2>errfile)delimiter(')operator(\))operator(;)
+
+comment(// -----------------------------)
+
+comment(// Run a command, handling its result code or signal.)
+local_variable($pid) operator(=) ident(pcntl_fork)operator(()operator(\))operator(;)
+reserved(if) operator(()local_variable($pid) operator(==) integer(-1)operator(\)) operator({)
+ reserved(die)operator(()delimiter(')string(cannot fork)delimiter(')operator(\))operator(;)
+operator(}) reserved(elseif) operator(()local_variable($pid)operator(\)) operator({)
+ ident(pcntl_waitpid)operator(()local_variable($pid)operator(,) local_variable($status)operator(\))operator(;)
+ reserved(if) operator(()ident(pcntl_wifexited)operator(()local_variable($status)operator(\))operator(\)) operator({)
+ local_variable($status) operator(=) ident(pcntl_wexitstatus)operator(()local_variable($status)operator(\))operator(;)
+ pre_type(echo) delimiter(")string(program exited with status )local_variable($status)char(\\n)delimiter(")operator(;)
+ operator(}) reserved(elseif) operator(()ident(pcntl_wifsignaled)operator(()local_variable($status)operator(\))operator(\)) operator({)
+ local_variable($signal) operator(=) ident(pcntl_wtermsig)operator(()local_variable($status)operator(\))operator(;)
+ pre_type(echo) delimiter(")string(program killed by signal )local_variable($signal)char(\\n)delimiter(")operator(;)
+ operator(}) reserved(elseif) operator(()ident(pcntl_wifstopped)operator(()local_variable($status)operator(\))operator(\)) operator({)
+ local_variable($signal) operator(=) ident(pcntl_wstopsig)operator(()local_variable($status)operator(\))operator(;)
+ pre_type(echo) delimiter(")string(program stopped by signal )local_variable($signal)char(\\n)delimiter(")operator(;)
+ operator(})
+operator(}) reserved(else) operator({)
+ ident(pcntl_exec)operator(()local_variable($program)operator(,) local_variable($args)operator(\))operator(;)
+operator(})
+
+comment(// -----------------------------)
+
+comment(// Run a command while blocking interrupt signals.)
+local_variable($pid) operator(=) ident(pcntl_fork)operator(()operator(\))operator(;)
+reserved(if) operator(()local_variable($pid) operator(==) integer(-1)operator(\)) operator({)
+ reserved(die)operator(()delimiter(')string(cannot fork)delimiter(')operator(\))operator(;)
+operator(}) reserved(elseif) operator(()local_variable($pid)operator(\)) operator({)
+ comment(// parent catches INT and berates user)
+ reserved(declare)operator(()ident(ticks) operator(=) integer(1)operator(\))operator(;)
+ pre_type(function) ident(handle_sigint)operator(()local_variable($signal)operator(\)) operator({)
+ pre_type(echo) delimiter(")string(Tsk tsk, no process interruptus)char(\\n)delimiter(")operator(;)
+ operator(})
+ ident(pcntl_signal)operator(()constant(SIGINT)operator(,) delimiter(')string(handle_sigint)delimiter(')operator(\))operator(;)
+ reserved(while) operator(()operator(!)ident(pcntl_waitpid)operator(()local_variable($pid)operator(,) local_variable($status)operator(,) constant(WNOHANG)operator(\))operator(\)) operator({)operator(})
+operator(}) reserved(else) operator({)
+ comment(// child ignores INT and does its thing)
+ ident(pcntl_signal)operator(()constant(SIGINT)operator(,) constant(SIG_IGN)operator(\))operator(;)
+ ident(pcntl_exec)operator(()delimiter(')string(/bin/sleep)delimiter(')operator(,) pre_type(array)operator(()delimiter(')string(10)delimiter(')operator(\))operator(\))operator(;)
+operator(})
+
+comment(// -----------------------------)
+
+comment(// Since there is no direct access to execv(\) and friends, and)
+comment(// pcntl_exec(\) won't let us supply an alternate program name)
+comment(// in the argument list, there is no way to run a command with)
+comment(// a different name in the process table.)
+
+comment(// @@PLEAC@@_16.3)
+comment(// Transfer control to the shell to run another program.)
+ident(pcntl_exec)operator(()delimiter(')string(/bin/sh)delimiter(')operator(,) pre_type(array)operator(()delimiter(')string(-c)delimiter(')operator(,) delimiter(')string(archive *.data)delimiter(')operator(\))operator(\))operator(;)
+comment(// Transfer control directly to another program.)
+ident(pcntl_exec)operator(()delimiter(')string(/path/to/archive)delimiter(')operator(,) pre_type(array)operator(()delimiter(')string(accounting.data)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// @@PLEAC@@_16.4)
+comment(// Handle each line in the output of a process.)
+local_variable($readme) operator(=) ident(popen)operator(()delimiter(')string(program arguments)delimiter(')operator(,) delimiter(')string(r)delimiter(')operator(\))operator(;)
+reserved(while) operator(()operator(!)ident(feof)operator(()local_variable($readme)operator(\))operator(\)) operator({)
+ local_variable($line) operator(=) ident(fgets)operator(()local_variable($readme)operator(\))operator(;)
+ reserved(if) operator(()local_variable($line) operator(===) pre_type(false)operator(\)) reserved(break)operator(;)
+ comment(// ...)
+operator(})
+ident(pclose)operator(()local_variable($readme)operator(\))operator(;)
+
+comment(// -----------------------------)
+
+comment(// Write to the input of a process.)
+local_variable($writeme) operator(=) ident(popen)operator(()delimiter(')string(program arguments)delimiter(')operator(,) delimiter(')string(w)delimiter(')operator(\))operator(;)
+ident(fwrite)operator(()local_variable($writeme)operator(,) delimiter(')string(data)delimiter(')operator(\))operator(;)
+ident(pclose)operator(()local_variable($writeme)operator(\))operator(;)
+
+comment(// -----------------------------)
+
+comment(// Wait for a process to complete.)
+local_variable($f) operator(=) ident(popen)operator(()delimiter(')string(sleep 1000000)delimiter(')operator(,) delimiter(')string(r)delimiter(')operator(\))operator(;) comment(// child goes to sleep)
+ident(pclose)operator(()local_variable($f)operator(\))operator(;) comment(// and parent goes to lala land)
+
+comment(// -----------------------------)
+
+local_variable($writeme) operator(=) ident(popen)operator(()delimiter(')string(program arguments)delimiter(')operator(,) delimiter(')string(w)delimiter(')operator(\))operator(;)
+ident(fwrite)operator(()local_variable($writeme)operator(,) delimiter(")string(hello)char(\\n)delimiter(")operator(\))operator(;) comment(// program will get hello\\n on STDIN)
+ident(pclose)operator(()local_variable($writeme)operator(\))operator(;) comment(// program will get EOF on STDIN)
+
+comment(// -----------------------------)
+
+comment(// Output buffering callback that sends output to the pager.)
+pre_type(function) ident(ob_pager)operator(()local_variable($output)operator(,) local_variable($mode)operator(\)) operator({)
+ pre_type(static) local_variable($pipe)operator(;)
+ reserved(if) operator(()local_variable($mode) operator(&) constant(PHP_OUTPUT_HANDLER_START)operator(\)) operator({)
+ local_variable($pager) operator(=) ident(getenv)operator(()delimiter(')string(PAGER)delimiter(')operator(\))operator(;)
+ reserved(if) operator(()operator(!)local_variable($pager)operator(\)) local_variable($pager) operator(=) delimiter(')string(/usr/bin/less)delimiter(')operator(;) comment(// XXX: might not exist)
+ local_variable($pipe) operator(=) ident(popen)operator(()local_variable($pager)operator(,) delimiter(')string(w)delimiter(')operator(\))operator(;)
+ operator(})
+ ident(fwrite)operator(()local_variable($pipe)operator(,) local_variable($output)operator(\))operator(;)
+ reserved(if) operator(()local_variable($mode) operator(&) constant(PHP_OUTPUT_HANDLER_END)operator(\)) operator({)
+ ident(pclose)operator(()local_variable($pipe)operator(\))operator(;)
+ operator(})
+operator(})
+
+comment(// Redirect standard output to the pager.)
+ident(ob_start)operator(()delimiter(')string(ob_pager)delimiter(')operator(\))operator(;)
+
+comment(// Do something useful that writes to standard output, then)
+comment(// close the output buffer.)
+comment(// ...)
+ident(ob_end_flush)operator(()operator(\))operator(;)
+
+comment(// @@PLEAC@@_16.5)
+comment(// Output buffering: Only display a certain number of lines of output.)
+pre_type(class) constant(Head) operator({)
+ pre_type(function) constant(Head)operator(()local_variable($lines)operator(=)integer(20)operator(\)) operator({)
+ local_variable($this)operator(->)ident(lines) operator(=) local_variable($lines)operator(;)
+ operator(})
+
+ pre_type(function) ident(filter)operator(()local_variable($output)operator(,) local_variable($mode)operator(\)) operator({)
+ local_variable($result) operator(=) pre_type(array)operator(()operator(\))operator(;)
+ local_variable($newline) operator(=) delimiter(')delimiter(')operator(;)
+ reserved(if) operator(()ident(strlen)operator(()local_variable($output)operator(\)) operator(>) integer(0) operator(&)operator(&) local_variable($output)operator([)ident(strlen)operator(()local_variable($output)operator(\)) operator(-) integer(1)operator(]) operator(==) delimiter(")char(\\n)delimiter(")operator(\)) operator({)
+ local_variable($newline) operator(=) delimiter(")char(\\n)delimiter(")operator(;)
+ local_variable($output) operator(=) ident(substr)operator(()local_variable($output)operator(,) integer(0)operator(,) integer(-1)operator(\))operator(;)
+ operator(})
+ reserved(foreach) operator(()ident(explode)operator(()delimiter(")char(\\n)delimiter(")operator(,) local_variable($output)operator(\)) reserved(as) local_variable($i) operator(=>) local_variable($line)operator(\)) operator({)
+ reserved(if) operator(()local_variable($this)operator(->)ident(lines) operator(>) integer(0)operator(\)) operator({)
+ local_variable($this)operator(->)ident(lines)operator(--)operator(;)
+ local_variable($result)operator([)operator(]) operator(=) local_variable($line)operator(;)
+ operator(})
+ operator(})
+ reserved(return) local_variable($result) operator(?) ident(implode)operator(()delimiter(")char(\\n)delimiter(")operator(,) local_variable($result)operator(\)) operator(.) local_variable($newline) operator(:) delimiter(')delimiter(')operator(;)
+ operator(})
+operator(})
+
+comment(// Output buffering: Prepend line numbers to each line of output.)
+pre_type(class) constant(Number) operator({)
+ pre_type(function) constant(Number)operator(()operator(\)) operator({)
+ local_variable($this)operator(->)ident(line_number) operator(=) integer(0)operator(;)
+ operator(})
+
+ pre_type(function) ident(filter)operator(()local_variable($output)operator(,) local_variable($mode)operator(\)) operator({)
+ local_variable($result) operator(=) pre_type(array)operator(()operator(\))operator(;)
+ local_variable($newline) operator(=) delimiter(')delimiter(')operator(;)
+ reserved(if) operator(()ident(strlen)operator(()local_variable($output)operator(\)) operator(>) integer(0) operator(&)operator(&) local_variable($output)operator([)ident(strlen)operator(()local_variable($output)operator(\)) operator(-) integer(1)operator(]) operator(==) delimiter(")char(\\n)delimiter(")operator(\)) operator({)
+ local_variable($newline) operator(=) delimiter(")char(\\n)delimiter(")operator(;)
+ local_variable($output) operator(=) ident(substr)operator(()local_variable($output)operator(,) integer(0)operator(,) integer(-1)operator(\))operator(;)
+ operator(})
+ reserved(foreach) operator(()ident(explode)operator(()delimiter(")char(\\n)delimiter(")operator(,) local_variable($output)operator(\)) reserved(as) local_variable($i) operator(=>) local_variable($line)operator(\)) operator({)
+ local_variable($this)operator(->)ident(line_number)operator(++)operator(;)
+ local_variable($result)operator([)operator(]) operator(=) local_variable($this)operator(->)ident(line_number) operator(.) delimiter(')string(: )delimiter(') operator(.) local_variable($line)operator(;)
+ operator(})
+ reserved(return) ident(implode)operator(()delimiter(")char(\\n)delimiter(")operator(,) local_variable($result)operator(\)) operator(.) local_variable($newline)operator(;)
+ operator(})
+operator(})
+
+comment(// Output buffering: Prepend "> " to each line of output.)
+pre_type(class) constant(Quote) operator({)
+ pre_type(function) constant(Quote)operator(()operator(\)) operator({)
+ operator(})
+
+ pre_type(function) ident(filter)operator(()local_variable($output)operator(,) local_variable($mode)operator(\)) operator({)
+ local_variable($result) operator(=) pre_type(array)operator(()operator(\))operator(;)
+ local_variable($newline) operator(=) delimiter(')delimiter(')operator(;)
+ reserved(if) operator(()ident(strlen)operator(()local_variable($output)operator(\)) operator(>) integer(0) operator(&)operator(&) local_variable($output)operator([)ident(strlen)operator(()local_variable($output)operator(\)) operator(-) integer(1)operator(]) operator(==) delimiter(")char(\\n)delimiter(")operator(\)) operator({)
+ local_variable($newline) operator(=) delimiter(")char(\\n)delimiter(")operator(;)
+ local_variable($output) operator(=) ident(substr)operator(()local_variable($output)operator(,) integer(0)operator(,) integer(-1)operator(\))operator(;)
+ operator(})
+ reserved(foreach) operator(()ident(explode)operator(()delimiter(")char(\\n)delimiter(")operator(,) local_variable($output)operator(\)) reserved(as) local_variable($i) operator(=>) local_variable($line)operator(\)) operator({)
+ local_variable($result)operator([)operator(]) operator(=) delimiter(")string(> )local_variable($line)delimiter(")operator(;)
+ operator(})
+ reserved(return) ident(implode)operator(()delimiter(")char(\\n)delimiter(")operator(,) local_variable($result)operator(\)) operator(.) local_variable($newline)operator(;)
+ operator(})
+operator(})
+
+comment(// Use arrays as callbacks to register filter methods.)
+ident(ob_start)operator(()pre_type(array)operator(()pre_type(new) constant(Head)operator(()integer(100)operator(\))operator(,) delimiter(')string(filter)delimiter(')operator(\))operator(\))operator(;)
+ident(ob_start)operator(()pre_type(array)operator(()pre_type(new) constant(Number)operator(()operator(\))operator(,) delimiter(')string(filter)delimiter(')operator(\))operator(\))operator(;)
+ident(ob_start)operator(()pre_type(array)operator(()pre_type(new) constant(Quote)operator(()operator(\))operator(,) delimiter(')string(filter)delimiter(')operator(\))operator(\))operator(;)
+
+comment(// Act like /bin/cat.)
+reserved(while) operator(()operator(!)ident(feof)operator(()constant(STDIN)operator(\))operator(\)) operator({)
+ local_variable($line) operator(=) ident(fgets)operator(()constant(STDIN)operator(\))operator(;)
+ reserved(if) operator(()local_variable($line) operator(===) pre_type(false)operator(\)) reserved(break)operator(;)
+ pre_type(echo) local_variable($line)operator(;)
+operator(})
+
+comment(// Should match number of calls to ob_start(\).)
+ident(ob_end_flush)operator(()operator(\))operator(;)
+ident(ob_end_flush)operator(()operator(\))operator(;)
+ident(ob_end_flush)operator(()operator(\))operator(;)
+
+comment(// @@PLEAC@@_16.6)
+comment(// Process command-line arguments using fopen(\). PHP supports URLs for)
+comment(// filenames as long as the "allow_url_fopen" configuration option is set.)
+comment(//)
+comment(// Valid URL protocols include:)
+comment(// - http://www.myserver.com/myfile.html)
+comment(// - ftp://ftp.myserver.com/myfile.txt)
+comment(// - compress.zlib://myfile.gz)
+comment(// - php://stdin)
+comment(//)
+comment(// See http://www.php.net/manual/en/wrappers.php for details.)
+comment(//)
+local_variable($filenames) operator(=) ident(array_slice)operator(()local_variable($argv)operator(,) integer(1)operator(\))operator(;)
+reserved(if) operator(()operator(!)local_variable($filenames)operator(\)) local_variable($filenames) operator(=) pre_type(array)operator(()delimiter(')string(php://stdin)delimiter(')operator(\))operator(;)
+reserved(foreach) operator(()local_variable($filenames) reserved(as) local_variable($filename)operator(\)) operator({)
+ local_variable($handle) operator(=) operator(@)ident(fopen)operator(()local_variable($filename)operator(,) delimiter(')string(r)delimiter(')operator(\))operator(;)
+ reserved(if) operator(()local_variable($handle)operator(\)) operator({)
+ reserved(while) operator(()operator(!)ident(feof)operator(()local_variable($handle)operator(\))operator(\)) operator({)
+ local_variable($line) operator(=) ident(fgets)operator(()local_variable($handle)operator(\))operator(;)
+ reserved(if) operator(()local_variable($line) operator(===) pre_type(false)operator(\)) reserved(break)operator(;)
+ comment(// ...)
+ operator(})
+ ident(fclose)operator(()local_variable($handle)operator(\))operator(;)
+ operator(}) reserved(else) operator({)
+ reserved(die)operator(()delimiter(")string(can't open )local_variable($filename)char(\\n)delimiter(")operator(\))operator(;)
+ operator(})
+operator(})
+
+comment(// @@PLEAC@@_16.7)
+local_variable($output) operator(=) error(`)ident(cmd) integer(2)operator(>)operator(&)integer(1)error(`)operator(;) comment(// with backticks)
+comment(// or)
+local_variable($ph) operator(=) ident(popen)operator(()delimiter(')string(cmd 2>&1)delimiter(')operator(\))operator(;) comment(// with an open pipe)
+reserved(while) operator(()operator(!)ident(feof)operator(()local_variable($ph)operator(\))operator(\)) operator({) local_variable($line) operator(=) ident(fgets)operator(()local_variable($ph)operator(\))operator(;) operator(}) comment(// plus a read)
+comment(// -----------------------------)
+local_variable($output) operator(=) error(`)ident(cmd) integer(2)operator(>)operator(/)ident(dev)operator(/)pre_type(null)error(`)operator(;) comment(// with backticks)
+comment(// or)
+local_variable($ph) operator(=) ident(popen)operator(()delimiter(')string(cmd 2>/dev/null)delimiter(')operator(\))operator(;) comment(// with an open pipe)
+reserved(while) operator(()operator(!)ident(feof)operator(()local_variable($ph)operator(\))operator(\)) operator({) local_variable($line) operator(=) ident(fgets)operator(()local_variable($ph)operator(\))operator(;) operator(}) comment(// plus a read)
+comment(// -----------------------------)
+local_variable($output) operator(=) error(`)ident(cmd) integer(2)operator(>)operator(&)integer(1) integer(1)operator(>)operator(/)ident(dev)operator(/)pre_type(null)error(`)operator(;) comment(// with backticks)
+comment(// or)
+local_variable($ph) operator(=) ident(popen)operator(()delimiter(')string(cmd 2>&1 1>/dev/null)delimiter(')operator(\))operator(;) comment(// with an open pipe)
+reserved(while) operator(()operator(!)ident(feof)operator(()local_variable($ph)operator(\))operator(\)) operator({) local_variable($line) operator(=) ident(fgets)operator(()local_variable($ph)operator(\))operator(;) operator(}) comment(// plus a read)
+comment(// -----------------------------)
+local_variable($output) operator(=) error(`)ident(cmd) integer(3)operator(>)operator(&)integer(1) integer(1)operator(>)operator(&)integer(2) integer(2)operator(>)operator(&)integer(3) integer(3)operator(>)operator(&)operator(-)error(`)operator(;) comment(// with backticks)
+comment(// or)
+local_variable($ph) operator(=) ident(popen)operator(()delimiter(')string(cmd 3>&1 1>&2 2>&3 3>&-|)delimiter(')operator(\))operator(;) comment(// with an open pipe)
+reserved(while) operator(()operator(!)ident(feof)operator(()local_variable($ph)operator(\))operator(\)) operator({) local_variable($line) operator(=) ident(fgets)operator(()local_variable($ph)operator(\))operator(;) operator(}) comment(// plus a read)
+comment(// -----------------------------)
+ident(exec)operator(()delimiter(')string(program args 1>/tmp/program.stdout 2>/tmp/program.stderr)delimiter(')operator(\))operator(;)
+comment(// -----------------------------)
+local_variable($output) operator(=) error(`)ident(cmd) integer(3)operator(>)operator(&)integer(1) integer(1)operator(>)operator(&)integer(2) integer(2)operator(>)operator(&)integer(3) integer(3)operator(>)operator(&)operator(-)error(`)operator(;)
+comment(// -----------------------------)
+local_variable($fd3) operator(=) local_variable($fd1)operator(;)
+local_variable($fd1) operator(=) local_variable($fd2)operator(;)
+local_variable($fd2) operator(=) local_variable($fd3)operator(;)
+local_variable($fd3) operator(=) pre_type(null)operator(;)
+comment(// -----------------------------)
+ident(exec)operator(()delimiter(')string(prog args 1>tmpfile 2>&1)delimiter(')operator(\))operator(;)
+ident(exec)operator(()delimiter(')string(prog args 2>&1 1>tmpfile)delimiter(')operator(\))operator(;)
+comment(// -----------------------------)
+comment(// exec('prog args 1>tmpfile 2>&1'\);)
+local_variable($fd1) operator(=) delimiter(")string(tmpfile)delimiter(")operator(;) comment(// change stdout destination first)
+local_variable($fd2) operator(=) local_variable($fd1)operator(;) comment(// now point stderr there, too)
+comment(// -----------------------------)
+comment(// exec('prog args 2>&1 1>tmpfile'\);)
+local_variable($fd2) operator(=) local_variable($fd1)operator(;) comment(// stderr same destination as stdout)
+local_variable($fd1) operator(=) delimiter(")string(tmpfile)delimiter(")operator(;) comment(// but change stdout destination)
+
+comment(// @@PLEAC@@_16.8)
+comment(// Connect to input and output of a process.)
+local_variable($proc) operator(=) ident(proc_open)operator(()local_variable($program)operator(,)
+ pre_type(array)operator(()integer(0) operator(=>) pre_type(array)operator(()delimiter(')string(pipe)delimiter(')operator(,) delimiter(')string(r)delimiter(')operator(\))operator(,)
+ integer(1) operator(=>) pre_type(array)operator(()delimiter(')string(pipe)delimiter(')operator(,) delimiter(')string(w)delimiter(')operator(\))operator(\))operator(,)
+ local_variable($pipes)operator(\))operator(;)
+reserved(if) operator(()ident(is_resource)operator(()local_variable($proc)operator(\))operator(\)) operator({)
+ ident(fwrite)operator(()local_variable($pipes)operator([)integer(0)operator(])operator(,) delimiter(")string(here's your input)char(\\n)delimiter(")operator(\))operator(;)
+ ident(fclose)operator(()local_variable($pipes)operator([)integer(0)operator(])operator(\))operator(;)
+ pre_type(echo) ident(stream_get_contents)operator(()local_variable($pipes)operator([)integer(1)operator(])operator(\))operator(;)
+ ident(fclose)operator(()local_variable($pipes)operator([)integer(1)operator(])operator(\))operator(;)
+ local_variable($result_code) operator(=) ident(proc_close)operator(()local_variable($proc)operator(\))operator(;)
+ pre_type(echo) delimiter(")local_variable($result_code)char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// -----------------------------)
+
+local_variable($all) operator(=) pre_type(array)operator(()operator(\))operator(;)
+local_variable($outlines) operator(=) pre_type(array)operator(()operator(\))operator(;)
+local_variable($errlines) operator(=) pre_type(array)operator(()operator(\))operator(;)
+ident(exec)operator(()delimiter(")string(( )local_variable($cmd)string( | sed -e 's/^/stdout: /' \) 2>&1)delimiter(")operator(,) local_variable($all)operator(\))operator(;)
+reserved(foreach) operator(()local_variable($all) reserved(as) local_variable($line)operator(\)) operator({)
+ local_variable($pos) operator(=) ident(strpos)operator(()local_variable($line)operator(,) delimiter(')string(stdout: )delimiter(')operator(\))operator(;)
+ reserved(if) operator(()local_variable($pos) operator(!==) pre_type(false) operator(&)operator(&) local_variable($pos) operator(==) integer(0)operator(\)) operator({)
+ local_variable($outlines)operator([)operator(]) operator(=) ident(substr)operator(()local_variable($line)operator(,) integer(8)operator(\))operator(;)
+ operator(}) reserved(else) operator({)
+ local_variable($errlines)operator([)operator(]) operator(=) local_variable($line)operator(;)
+ operator(})
+operator(})
+pre_type(print)operator(()delimiter(")string(STDOUT:)char(\\n)delimiter(")operator(\))operator(;)
+ident(print_r)operator(()local_variable($outlines)operator(\))operator(;)
+pre_type(print)operator(()delimiter(")char(\\n)delimiter(")operator(\))operator(;)
+pre_type(print)operator(()delimiter(")string(STDERR:)char(\\n)delimiter(")operator(\))operator(;)
+ident(print_r)operator(()local_variable($errlines)operator(\))operator(;)
+pre_type(print)operator(()delimiter(")char(\\n)delimiter(")operator(\))operator(;)
+
+comment(// @@PLEAC@@_16.9)
+local_variable($proc) operator(=) ident(proc_open)operator(()local_variable($cmd)operator(,)
+ pre_type(array)operator(()integer(0) operator(=>) pre_type(array)operator(()delimiter(')string(pipe)delimiter(')operator(,) delimiter(')string(r)delimiter(')operator(\))operator(,)
+ integer(1) operator(=>) pre_type(array)operator(()delimiter(')string(pipe)delimiter(')operator(,) delimiter(')string(w)delimiter(')operator(\))operator(,)
+ integer(2) operator(=>) pre_type(array)operator(()delimiter(')string(pipe)delimiter(')operator(,) delimiter(')string(w)delimiter(')operator(\))operator(\))operator(,)
+ local_variable($pipes)operator(\))operator(;)
+
+reserved(if) operator(()ident(is_resource)operator(()local_variable($proc)operator(\))operator(\)) operator({)
+ comment(// give end of file to kid, or feed him)
+ ident(fclose)operator(()local_variable($pipes)operator([)integer(0)operator(])operator(\))operator(;)
+
+ comment(// read till EOF)
+ local_variable($outlines) operator(=) pre_type(array)operator(()operator(\))operator(;)
+ reserved(while) operator(()operator(!)ident(feof)operator(()local_variable($pipes)operator([)integer(1)operator(])operator(\))operator(\)) operator({)
+ local_variable($line) operator(=) ident(fgets)operator(()local_variable($pipes)operator([)integer(1)operator(])operator(\))operator(;)
+ reserved(if) operator(()local_variable($line) operator(===) pre_type(false)operator(\)) reserved(break)operator(;)
+ local_variable($outlines)operator([)operator(]) operator(=) ident(rtrim)operator(()local_variable($line)operator(\))operator(;)
+ operator(})
+
+ comment(// XXX: block potential if massive)
+ local_variable($errlines) operator(=) pre_type(array)operator(()operator(\))operator(;)
+ reserved(while) operator(()operator(!)ident(feof)operator(()local_variable($pipes)operator([)integer(2)operator(])operator(\))operator(\)) operator({)
+ local_variable($line) operator(=) ident(fgets)operator(()local_variable($pipes)operator([)integer(2)operator(])operator(\))operator(;)
+ reserved(if) operator(()local_variable($line) operator(===) pre_type(false)operator(\)) reserved(break)operator(;)
+ local_variable($errlines)operator([)operator(]) operator(=) ident(rtrim)operator(()local_variable($line)operator(\))operator(;)
+ operator(})
+
+ ident(fclose)operator(()local_variable($pipes)operator([)integer(1)operator(])operator(\))operator(;)
+ ident(fclose)operator(()local_variable($pipes)operator([)integer(2)operator(])operator(\))operator(;)
+ ident(proc_close)operator(()local_variable($proc)operator(\))operator(;)
+
+ pre_type(print)operator(()delimiter(")string(STDOUT:)char(\\n)delimiter(")operator(\))operator(;)
+ ident(print_r)operator(()local_variable($outlines)operator(\))operator(;)
+ pre_type(print)operator(()delimiter(")char(\\n)delimiter(")operator(\))operator(;)
+ pre_type(print)operator(()delimiter(")string(STDERR:)char(\\n)delimiter(")operator(\))operator(;)
+ ident(print_r)operator(()local_variable($errlines)operator(\))operator(;)
+ pre_type(print)operator(()delimiter(")char(\\n)delimiter(")operator(\))operator(;)
+operator(})
+
+comment(// -----------------------------)
+
+comment(// cmd3sel - control all three of kids in, out, and error.)
+local_variable($cmd) operator(=) delimiter(")string(grep vt33 /none/such - /etc/termcap)delimiter(")operator(;)
+local_variable($proc) operator(=) ident(proc_open)operator(()local_variable($cmd)operator(,)
+ pre_type(array)operator(()integer(0) operator(=>) pre_type(array)operator(()delimiter(')string(pipe)delimiter(')operator(,) delimiter(')string(r)delimiter(')operator(\))operator(,)
+ integer(1) operator(=>) pre_type(array)operator(()delimiter(')string(pipe)delimiter(')operator(,) delimiter(')string(w)delimiter(')operator(\))operator(,)
+ integer(2) operator(=>) pre_type(array)operator(()delimiter(')string(pipe)delimiter(')operator(,) delimiter(')string(w)delimiter(')operator(\))operator(\))operator(,)
+ local_variable($pipes)operator(\))operator(;)
+
+reserved(if) operator(()ident(is_resource)operator(()local_variable($proc)operator(\))operator(\)) operator({)
+ ident(fwrite)operator(()local_variable($pipes)operator([)integer(0)operator(])operator(,) delimiter(")string(This line has a vt33 lurking in it)char(\\n)delimiter(")operator(\))operator(;)
+ ident(fclose)operator(()local_variable($pipes)operator([)integer(0)operator(])operator(\))operator(;)
+
+ local_variable($readers) operator(=) pre_type(array)operator(()local_variable($pipes)operator([)integer(1)operator(])operator(,) local_variable($pipes)operator([)integer(2)operator(])operator(\))operator(;)
+ reserved(while) operator(()ident(stream_select)operator(()local_variable($read)operator(=)local_variable($readers)operator(,)
+ local_variable($write)operator(=)pre_type(null)operator(,)
+ local_variable($except)operator(=)pre_type(null)operator(,)
+ integer(0)operator(,) integer(200000)operator(\)) operator(>) integer(0)operator(\)) operator({)
+ reserved(foreach) operator(()local_variable($read) reserved(as) local_variable($stream)operator(\)) operator({)
+ local_variable($line) operator(=) ident(fgets)operator(()local_variable($stream)operator(\))operator(;)
+ reserved(if) operator(()local_variable($line) operator(!==) pre_type(false)operator(\)) operator({)
+ reserved(if) operator(()local_variable($stream) operator(===) local_variable($pipes)operator([)integer(1)operator(])operator(\)) operator({)
+ pre_type(print) delimiter(")string(STDOUT: )local_variable($line)delimiter(")operator(;)
+ operator(}) reserved(else) operator({)
+ pre_type(print) delimiter(")string(STDERR: )local_variable($line)delimiter(")operator(;)
+ operator(})
+ operator(})
+ reserved(if) operator(()ident(feof)operator(()local_variable($stream)operator(\))operator(\)) operator({)
+ local_variable($readers) operator(=) ident(array_diff)operator(()local_variable($readers)operator(,) pre_type(array)operator(()local_variable($stream)operator(\))operator(\))operator(;)
+ operator(})
+ operator(})
+ operator(})
+
+ ident(fclose)operator(()local_variable($pipes)operator([)integer(1)operator(])operator(\))operator(;)
+ ident(fclose)operator(()local_variable($pipes)operator([)integer(2)operator(])operator(\))operator(;)
+ ident(proc_close)operator(()local_variable($proc)operator(\))operator(;)
+operator(})
+
+comment(// @@PLEAC@@_16.10)
+comment(// PHP supports fork/exec/wait but not pipe. However, it does)
+comment(// support socketpair, which can do everything pipes can as well)
+comment(// as bidirectional communication. The original recipes have been)
+comment(// modified here to use socketpair only.)
+
+comment(// -----------------------------)
+
+comment(// pipe1 - use socketpair and fork so parent can send to child)
+local_variable($sockets) operator(=) pre_type(array)operator(()operator(\))operator(;)
+reserved(if) operator(()operator(!)ident(socket_create_pair)operator(()constant(AF_UNIX)operator(,) constant(SOCK_STREAM)operator(,) integer(0)operator(,) local_variable($sockets)operator(\))operator(\)) operator({)
+ reserved(die)operator(()ident(socket_strerror)operator(()ident(socket_last_error)operator(()operator(\))operator(\))operator(\))operator(;)
+operator(})
+pre_type(list)operator(()local_variable($reader)operator(,) local_variable($writer)operator(\)) operator(=) local_variable($sockets)operator(;)
+
+local_variable($pid) operator(=) ident(pcntl_fork)operator(()operator(\))operator(;)
+reserved(if) operator(()local_variable($pid) operator(==) integer(-1)operator(\)) operator({)
+ reserved(die)operator(()delimiter(')string(cannot fork)delimiter(')operator(\))operator(;)
+operator(}) reserved(elseif) operator(()local_variable($pid)operator(\)) operator({)
+ ident(socket_close)operator(()local_variable($reader)operator(\))operator(;)
+ local_variable($line) operator(=) ident(sprintf)operator(()delimiter(")string(Parent Pid %d is sending this)char(\\n)delimiter(")operator(,) ident(getmypid)operator(()operator(\))operator(\))operator(;)
+ reserved(if) operator(()operator(!)ident(socket_write)operator(()local_variable($writer)operator(,) local_variable($line)operator(,) ident(strlen)operator(()local_variable($line)operator(\))operator(\))operator(\)) operator({)
+ ident(socket_close)operator(()local_variable($writer)operator(\))operator(;)
+ reserved(die)operator(()ident(socket_strerror)operator(()ident(socket_last_error)operator(()operator(\))operator(\))operator(\))operator(;)
+ operator(})
+ ident(socket_close)operator(()local_variable($writer)operator(\))operator(;)
+ ident(pcntl_waitpid)operator(()local_variable($pid)operator(,) local_variable($status)operator(\))operator(;)
+operator(}) reserved(else) operator({)
+ ident(socket_close)operator(()local_variable($writer)operator(\))operator(;)
+ local_variable($line) operator(=) ident(socket_read)operator(()local_variable($reader)operator(,) integer(1024)operator(,) constant(PHP_NORMAL_READ)operator(\))operator(;)
+ ident(printf)operator(()delimiter(")string(Child Pid %d just read this: `%s')char(\\n)delimiter(")operator(,) ident(getmypid)operator(()operator(\))operator(,) ident(rtrim)operator(()local_variable($line)operator(\))operator(\))operator(;)
+ ident(socket_close)operator(()local_variable($reader)operator(\))operator(;) comment(// this will happen anyway)
+ reserved(exit)operator(()integer(0)operator(\))operator(;)
+operator(})
+
+comment(// -----------------------------)
+
+comment(// pipe2 - use socketpair and fork so child can send to parent)
+local_variable($sockets) operator(=) pre_type(array)operator(()operator(\))operator(;)
+reserved(if) operator(()operator(!)ident(socket_create_pair)operator(()constant(AF_UNIX)operator(,) constant(SOCK_STREAM)operator(,) integer(0)operator(,) local_variable($sockets)operator(\))operator(\)) operator({)
+ reserved(die)operator(()ident(socket_strerror)operator(()ident(socket_last_error)operator(()operator(\))operator(\))operator(\))operator(;)
+operator(})
+pre_type(list)operator(()local_variable($reader)operator(,) local_variable($writer)operator(\)) operator(=) local_variable($sockets)operator(;)
+
+local_variable($pid) operator(=) ident(pcntl_fork)operator(()operator(\))operator(;)
+reserved(if) operator(()local_variable($pid) operator(==) integer(-1)operator(\)) operator({)
+ reserved(die)operator(()delimiter(')string(cannot fork)delimiter(')operator(\))operator(;)
+operator(}) reserved(elseif) operator(()local_variable($pid)operator(\)) operator({)
+ ident(socket_close)operator(()local_variable($writer)operator(\))operator(;)
+ local_variable($line) operator(=) ident(socket_read)operator(()local_variable($reader)operator(,) integer(1024)operator(,) constant(PHP_NORMAL_READ)operator(\))operator(;)
+ ident(printf)operator(()delimiter(")string(Parent Pid %d just read this: `%s')char(\\n)delimiter(")operator(,) ident(getmypid)operator(()operator(\))operator(,) ident(rtrim)operator(()local_variable($line)operator(\))operator(\))operator(;)
+ ident(socket_close)operator(()local_variable($reader)operator(\))operator(;)
+ ident(pcntl_waitpid)operator(()local_variable($pid)operator(,) local_variable($status)operator(\))operator(;)
+operator(}) reserved(else) operator({)
+ ident(socket_close)operator(()local_variable($reader)operator(\))operator(;)
+ local_variable($line) operator(=) ident(sprintf)operator(()delimiter(")string(Child Pid %d is sending this)char(\\n)delimiter(")operator(,) ident(getmypid)operator(()operator(\))operator(\))operator(;)
+ reserved(if) operator(()operator(!)ident(socket_write)operator(()local_variable($writer)operator(,) local_variable($line)operator(,) ident(strlen)operator(()local_variable($line)operator(\))operator(\))operator(\)) operator({)
+ ident(socket_close)operator(()local_variable($writer)operator(\))operator(;)
+ reserved(die)operator(()ident(socket_strerror)operator(()ident(socket_last_error)operator(()operator(\))operator(\))operator(\))operator(;)
+ operator(})
+ ident(socket_close)operator(()local_variable($writer)operator(\))operator(;) comment(// this will happen anyway)
+ reserved(exit)operator(()integer(0)operator(\))operator(;)
+operator(})
+
+comment(// -----------------------------)
+
+comment(// pipe3 and pipe4 demonstrate the use of perl's "forking open")
+comment(// feature to reimplement pipe1 and pipe2. pipe5 uses two pipes)
+comment(// to simulate socketpair. Since PHP supports socketpair but not)
+comment(// pipe, and does not have a "forking open" feature, these)
+comment(// examples are skipped here.)
+
+comment(// -----------------------------)
+
+comment(// pipe6 - bidirectional communication using socketpair)
+local_variable($sockets) operator(=) pre_type(array)operator(()operator(\))operator(;)
+reserved(if) operator(()operator(!)ident(socket_create_pair)operator(()constant(AF_UNIX)operator(,) constant(SOCK_STREAM)operator(,) integer(0)operator(,) local_variable($sockets)operator(\))operator(\)) operator({)
+ reserved(die)operator(()ident(socket_strerror)operator(()ident(socket_last_error)operator(()operator(\))operator(\))operator(\))operator(;)
+operator(})
+pre_type(list)operator(()local_variable($child)operator(,) local_variable($parent)operator(\)) operator(=) local_variable($sockets)operator(;)
+
+local_variable($pid) operator(=) ident(pcntl_fork)operator(()operator(\))operator(;)
+reserved(if) operator(()local_variable($pid) operator(==) integer(-1)operator(\)) operator({)
+ reserved(die)operator(()delimiter(')string(cannot fork)delimiter(')operator(\))operator(;)
+operator(}) reserved(elseif) operator(()local_variable($pid)operator(\)) operator({)
+ ident(socket_close)operator(()local_variable($parent)operator(\))operator(;)
+ local_variable($line) operator(=) ident(sprintf)operator(()delimiter(")string(Parent Pid %d is sending this)char(\\n)delimiter(")operator(,) ident(getmypid)operator(()operator(\))operator(\))operator(;)
+ reserved(if) operator(()operator(!)ident(socket_write)operator(()local_variable($child)operator(,) local_variable($line)operator(,) ident(strlen)operator(()local_variable($line)operator(\))operator(\))operator(\)) operator({)
+ ident(socket_close)operator(()local_variable($child)operator(\))operator(;)
+ reserved(die)operator(()ident(socket_strerror)operator(()ident(socket_last_error)operator(()operator(\))operator(\))operator(\))operator(;)
+ operator(})
+ local_variable($line) operator(=) ident(socket_read)operator(()local_variable($child)operator(,) integer(1024)operator(,) constant(PHP_NORMAL_READ)operator(\))operator(;)
+ ident(printf)operator(()delimiter(")string(Parent Pid %d just read this: `%s')char(\\n)delimiter(")operator(,) ident(getmypid)operator(()operator(\))operator(,) ident(rtrim)operator(()local_variable($line)operator(\))operator(\))operator(;)
+ ident(socket_close)operator(()local_variable($child)operator(\))operator(;)
+ ident(pcntl_waitpid)operator(()local_variable($pid)operator(,) local_variable($status)operator(\))operator(;)
+operator(}) reserved(else) operator({)
+ ident(socket_close)operator(()local_variable($child)operator(\))operator(;)
+ local_variable($line) operator(=) ident(socket_read)operator(()local_variable($parent)operator(,) integer(1024)operator(,) constant(PHP_NORMAL_READ)operator(\))operator(;)
+ ident(printf)operator(()delimiter(")string(Child Pid %d just read this: `%s')char(\\n)delimiter(")operator(,) ident(getmypid)operator(()operator(\))operator(,) ident(rtrim)operator(()local_variable($line)operator(\))operator(\))operator(;)
+ local_variable($line) operator(=) ident(sprintf)operator(()delimiter(")string(Child Pid %d is sending this)char(\\n)delimiter(")operator(,) ident(getmypid)operator(()operator(\))operator(\))operator(;)
+ reserved(if) operator(()operator(!)ident(socket_write)operator(()local_variable($parent)operator(,) local_variable($line)operator(,) ident(strlen)operator(()local_variable($line)operator(\))operator(\))operator(\)) operator({)
+ ident(socket_close)operator(()local_variable($parent)operator(\))operator(;)
+ reserved(die)operator(()ident(socket_strerror)operator(()ident(socket_last_error)operator(()operator(\))operator(\))operator(\))operator(;)
+ operator(})
+ ident(socket_close)operator(()local_variable($parent)operator(\))operator(;)
+ reserved(exit)operator(()integer(0)operator(\))operator(;)
+operator(})
+
+comment(// @@PLEAC@@_16.11)
+comment(// -----------------------------)
+comment(// % mkfifo /path/to/named.pipe)
+comment(// -----------------------------)
+
+local_variable($fifo) operator(=) ident(fopen)operator(()delimiter(')string(/path/to/named.pipe)delimiter(')operator(,) delimiter(')string(r)delimiter(')operator(\))operator(;)
+reserved(if) operator(()local_variable($fifo) operator(!==) pre_type(false)operator(\)) operator({)
+ reserved(while) operator(()operator(!)ident(feof)operator(()local_variable($fifo)operator(\))operator(\)) operator({)
+ local_variable($line) operator(=) ident(fgets)operator(()local_variable($fifo)operator(\))operator(;)
+ reserved(if) operator(()local_variable($line) operator(===) pre_type(false)operator(\)) reserved(break)operator(;)
+ pre_type(echo) delimiter(")string(Got: )local_variable($line)delimiter(")operator(;)
+ operator(})
+ ident(fclose)operator(()local_variable($fifo)operator(\))operator(;)
+operator(}) reserved(else) operator({)
+ reserved(die)operator(()delimiter(')string(could not open fifo for read)delimiter(')operator(\))operator(;)
+operator(})
+
+comment(// -----------------------------)
+
+local_variable($fifo) operator(=) ident(fopen)operator(()delimiter(')string(/path/to/named.pipe)delimiter(')operator(,) delimiter(')string(w)delimiter(')operator(\))operator(;)
+reserved(if) operator(()local_variable($fifo) operator(!==) pre_type(false)operator(\)) operator({)
+ ident(fwrite)operator(()local_variable($fifo)operator(,) delimiter(")string(Smoke this.)char(\\n)delimiter(")operator(\))operator(;)
+ ident(fclose)operator(()local_variable($fifo)operator(\))operator(;)
+operator(}) reserved(else) operator({)
+ reserved(die)operator(()delimiter(')string(could not open fifo for write)delimiter(')operator(\))operator(;)
+operator(})
+
+comment(// -----------------------------)
+comment(// % mkfifo ~/.plan # isn't this everywhere yet?)
+comment(// % mknod ~/.plan p # in case you don't have mkfifo)
+comment(// -----------------------------)
+
+comment(// dateplan - place current date and time in .plan file)
+reserved(while) operator(()pre_type(true)operator(\)) operator({)
+ local_variable($home) operator(=) ident(getenv)operator(()delimiter(')string(HOME)delimiter(')operator(\))operator(;)
+ local_variable($fifo) operator(=) ident(fopen)operator(()delimiter(")local_variable($home)string(/.plan)delimiter(")operator(,) delimiter(')string(w)delimiter(')operator(\))operator(;)
+ reserved(if) operator(()local_variable($fifo) operator(===) pre_type(false)operator(\)) operator({)
+ reserved(die)operator(()delimiter(")string(Couldn't open )local_variable($home)string(/.plan for writing.)char(\\n)delimiter(")operator(\))operator(;)
+ operator(})
+ ident(fwrite)operator(()local_variable($fifo)operator(,)
+ delimiter(')string(The current time is )delimiter(')
+ operator(.) ident(strftime)operator(()delimiter(')string(%a, %d %b %Y %H:%M:%S %z)delimiter(')operator(\))
+ operator(.) delimiter(")char(\\n)delimiter(")operator(\))operator(;)
+ ident(fclose)operator(()local_variable($fifo)operator(\))operator(;)
+ ident(sleep)operator(()integer(1)operator(\))operator(;)
+operator(})
+
+comment(// -----------------------------)
+
+comment(// fifolog - read and record log msgs from fifo)
+
+local_variable($fifo) operator(=) pre_type(null)operator(;)
+
+reserved(declare)operator(()ident(ticks) operator(=) integer(1)operator(\))operator(;)
+pre_type(function) ident(handle_alarm)operator(()local_variable($signal)operator(\)) operator({)
+ pre_type(global) local_variable($fifo)operator(;)
+ reserved(if) operator(()local_variable($fifo)operator(\)) ident(fclose)operator(()local_variable($fifo)operator(\))operator(;) comment(// move on to the next queued process)
+operator(})
+ident(pcntl_signal)operator(()constant(SIGALRM)operator(,) delimiter(')string(handle_alarm)delimiter(')operator(\))operator(;)
+
+reserved(while) operator(()pre_type(true)operator(\)) operator({)
+ ident(pcntl_alarm)operator(()integer(0)operator(\))operator(;) comment(// turn off alarm for blocking open)
+ local_variable($fifo) operator(=) ident(fopen)operator(()delimiter(')string(/tmp/log)delimiter(')operator(,) delimiter(')string(r)delimiter(')operator(\))operator(;)
+ reserved(if) operator(()local_variable($fifo) operator(===) pre_type(false)operator(\)) operator({)
+ reserved(die)operator(()delimiter(")string(can't open /tmp/log)delimiter(")operator(\))operator(;)
+ operator(})
+ ident(pcntl_alarm)operator(()integer(1)operator(\))operator(;) comment(// you have 1 second to log)
+
+ local_variable($service) operator(=) ident(fgets)operator(()local_variable($fifo)operator(\))operator(;)
+ reserved(if) operator(()local_variable($service) operator(===) pre_type(false)operator(\)) reserved(continue)operator(;) comment(// interrupt or nothing logged)
+ local_variable($service) operator(=) ident(rtrim)operator(()local_variable($service)operator(\))operator(;)
+
+ local_variable($message) operator(=) ident(fgets)operator(()local_variable($fifo)operator(\))operator(;)
+ reserved(if) operator(()local_variable($message) operator(===) pre_type(false)operator(\)) reserved(continue)operator(;) comment(// interrupt or nothing logged)
+ local_variable($message) operator(=) ident(rtrim)operator(()local_variable($message)operator(\))operator(;)
+
+ ident(pcntl_alarm)operator(()integer(0)operator(\))operator(;) comment(// turn off alarms for message processing)
+
+ reserved(if) operator(()local_variable($service) operator(==) delimiter(')string(http)delimiter(')operator(\)) operator({)
+ comment(// ignoring)
+ operator(}) reserved(elseif) operator(()local_variable($service) operator(==) delimiter(')string(login)delimiter(')operator(\)) operator({)
+ comment(// log to /var/log/login)
+ local_variable($log) operator(=) ident(fopen)operator(()delimiter(')string(/var/log/login)delimiter(')operator(,) delimiter(')string(a)delimiter(')operator(\))operator(;)
+ reserved(if) operator(()local_variable($log) operator(!==) pre_type(false)operator(\)) operator({)
+ ident(fwrite)operator(()local_variable($log)operator(,)
+ ident(strftime)operator(()delimiter(')string(%a, %d %b %Y %H:%M:%S %z)delimiter(')operator(\))
+ operator(.) delimiter(")string( )local_variable($service)string( )local_variable($message)char(\\n)delimiter(")operator(\))operator(;)
+ ident(fclose)operator(()local_variable($log)operator(\))operator(;)
+ operator(}) reserved(else) operator({)
+ ident(trigger_error)operator(()delimiter(")string(Couldn't log )local_variable($service)string( )local_variable($message)string( to /var/log/login)char(\\n)delimiter(")operator(,)
+ constant(E_USER_WARNING)operator(\))operator(;)
+ operator(})
+ operator(})
+operator(})
+
+comment(// @@PLEAC@@_16.12)
+comment(// sharetest - test shared variables across forks)
+
+local_variable($SHM_KEY) operator(=) ident(ftok)operator(()pre_constant(__FILE__)operator(,) ident(chr)operator(()integer(1)operator(\))operator(\))operator(;)
+local_variable($handle) operator(=) ident(sem_get)operator(()local_variable($SHM_KEY)operator(\))operator(;)
+local_variable($buffer) operator(=) ident(shm_attach)operator(()local_variable($handle)operator(,) integer(1024)operator(\))operator(;)
+
+comment(// The original recipe has an INT signal handler here. However, it)
+comment(// causes erratic behavior with PHP, and PHP seems to do the right)
+comment(// thing without it.)
+
+reserved(for) operator(()local_variable($i) operator(=) integer(0)operator(;) local_variable($i) operator(<) integer(10)operator(;) local_variable($i)operator(++)operator(\)) operator({)
+ local_variable($child) operator(=) ident(pcntl_fork)operator(()operator(\))operator(;)
+ reserved(if) operator(()local_variable($child) operator(==) integer(-1)operator(\)) operator({)
+ reserved(die)operator(()delimiter(')string(cannot fork)delimiter(')operator(\))operator(;)
+ operator(}) reserved(elseif) operator(()local_variable($child)operator(\)) operator({)
+ local_variable($kids)operator([)operator(]) operator(=) local_variable($child)operator(;) comment(// in case we care about their pids)
+ operator(}) reserved(else) operator({)
+ ident(squabble)operator(()operator(\))operator(;)
+ reserved(exit)operator(()operator(\))operator(;)
+ operator(})
+operator(})
+
+reserved(while) operator(()pre_type(true)operator(\)) operator({)
+ pre_type(print) delimiter(')string(Buffer is )delimiter(') operator(.) ident(shm_get_var)operator(()local_variable($buffer)operator(,) integer(1)operator(\)) operator(.) delimiter(")char(\\n)delimiter(")operator(;)
+ ident(sleep)operator(()integer(1)operator(\))operator(;)
+operator(})
+reserved(die)operator(()delimiter(')string(Not reached)delimiter(')operator(\))operator(;)
+
+pre_type(function) ident(squabble)operator(()operator(\)) operator({)
+ pre_type(global) local_variable($handle)operator(;)
+ pre_type(global) local_variable($buffer)operator(;)
+ local_variable($i) operator(=) integer(0)operator(;)
+ local_variable($pid) operator(=) ident(getmypid)operator(()operator(\))operator(;)
+ reserved(while) operator(()pre_type(true)operator(\)) operator({)
+ reserved(if) operator(()ident(preg_match)operator(()delimiter(")string(/^)local_variable($pid)char(\\\\)string(b/)delimiter(")operator(,) ident(shm_get_var)operator(()local_variable($buffer)operator(,) integer(1)operator(\))operator(\))operator(\)) reserved(continue)operator(;)
+ ident(sem_acquire)operator(()local_variable($handle)operator(\))operator(;)
+ local_variable($i)operator(++)operator(;)
+ ident(shm_put_var)operator(()local_variable($buffer)operator(,) integer(1)operator(,) delimiter(")local_variable($pid)string( )local_variable($i)delimiter(")operator(\))operator(;)
+ ident(sem_release)operator(()local_variable($handle)operator(\))operator(;)
+ operator(})
+operator(})
+
+comment(// Buffer is 14357 1)
+comment(// Buffer is 14355 3)
+comment(// Buffer is 14355 4)
+comment(// Buffer is 14354 5)
+comment(// Buffer is 14353 6)
+comment(// Buffer is 14351 8)
+comment(// Buffer is 14351 9)
+comment(// Buffer is 14350 10)
+comment(// Buffer is 14348 11)
+comment(// Buffer is 14348 12)
+comment(// Buffer is 14357 10)
+comment(// Buffer is 14357 11)
+comment(// Buffer is 14355 13)
+comment(// ...)
+
+comment(// @@PLEAC@@_16.13)
+comment(// Available signal constants)
+operator(%) ident(php) operator(-)ident(r) delimiter(')string(print_r(get_defined_constants(\)\);)delimiter(') operator(|) ident(grep) delimiter(')string(\\)string([SIG)delimiter(') operator(|) ident(grep) operator(-)ident(v) ident(_)
+ operator([)constant(SIGHUP)operator(]) operator(=>) integer(1)
+ operator([)constant(SIGINT)operator(]) operator(=>) integer(2)
+ operator([)constant(SIGQUIT)operator(]) operator(=>) integer(3)
+ operator([)constant(SIGILL)operator(]) operator(=>) integer(4)
+ operator([)constant(SIGTRAP)operator(]) operator(=>) integer(5)
+ operator([)constant(SIGABRT)operator(]) operator(=>) integer(6)
+ operator([)constant(SIGIOT)operator(]) operator(=>) integer(6)
+ operator([)constant(SIGBUS)operator(]) operator(=>) integer(7)
+ operator([)constant(SIGFPE)operator(]) operator(=>) integer(8)
+ operator([)constant(SIGKILL)operator(]) operator(=>) integer(9)
+ operator([)constant(SIGUSR1)operator(]) operator(=>) integer(10)
+ operator([)constant(SIGSEGV)operator(]) operator(=>) integer(11)
+ operator([)constant(SIGUSR2)operator(]) operator(=>) integer(12)
+ operator([)constant(SIGPIPE)operator(]) operator(=>) integer(13)
+ operator([)constant(SIGALRM)operator(]) operator(=>) integer(14)
+ operator([)constant(SIGTERM)operator(]) operator(=>) integer(15)
+ operator([)constant(SIGSTKFLT)operator(]) operator(=>) integer(16)
+ operator([)constant(SIGCLD)operator(]) operator(=>) integer(17)
+ operator([)constant(SIGCHLD)operator(]) operator(=>) integer(17)
+ operator([)constant(SIGCONT)operator(]) operator(=>) integer(18)
+ operator([)constant(SIGSTOP)operator(]) operator(=>) integer(19)
+ operator([)constant(SIGTSTP)operator(]) operator(=>) integer(20)
+ operator([)constant(SIGTTIN)operator(]) operator(=>) integer(21)
+ operator([)constant(SIGTTOU)operator(]) operator(=>) integer(22)
+ operator([)constant(SIGURG)operator(]) operator(=>) integer(23)
+ operator([)constant(SIGXCPU)operator(]) operator(=>) integer(24)
+ operator([)constant(SIGXFSZ)operator(]) operator(=>) integer(25)
+ operator([)constant(SIGVTALRM)operator(]) operator(=>) integer(26)
+ operator([)constant(SIGPROF)operator(]) operator(=>) integer(27)
+ operator([)constant(SIGWINCH)operator(]) operator(=>) integer(28)
+ operator([)constant(SIGPOLL)operator(]) operator(=>) integer(29)
+ operator([)constant(SIGIO)operator(]) operator(=>) integer(29)
+ operator([)constant(SIGPWR)operator(]) operator(=>) integer(30)
+ operator([)constant(SIGSYS)operator(]) operator(=>) integer(31)
+ operator([)constant(SIGBABY)operator(]) operator(=>) integer(31)
+
+comment(// Predefined signal handler constants)
+operator(%) ident(php) operator(-)ident(r) delimiter(')string(print_r(get_defined_constants(\)\);)delimiter(') operator(|) ident(grep) delimiter(')string(\\)string([SIG)delimiter(') operator(|) ident(grep) ident(_)
+ operator([)constant(SIG_IGN)operator(]) operator(=>) integer(1)
+ operator([)constant(SIG_DFL)operator(]) operator(=>) integer(0)
+ operator([)constant(SIG_ERR)operator(]) operator(=>) integer(-1)
+
+comment(// @@PLEAC@@_16.14)
+comment(// send pid a signal 9)
+ident(posix_kill)operator(()local_variable($pid)operator(,) integer(9)operator(\))operator(;)
+comment(// send whole job a signal 1)
+ident(posix_kill)operator(()local_variable($pgrp)operator(,) integer(-1)operator(\))operator(;)
+comment(// send myself a SIGUSR1)
+ident(posix_kill)operator(()ident(getmypid)operator(()operator(\))operator(,) constant(SIGUSR1)operator(\))operator(;)
+comment(// send a SIGHUP to processes in pids)
+reserved(foreach) operator(()local_variable($pids) reserved(as) local_variable($pid)operator(\)) ident(posix_kill)operator(()local_variable($pid)operator(,) constant(SIGHUP)operator(\))operator(;)
+
+comment(// -----------------------------)
+
+comment(// Use kill with pseudo-signal 0 to see if process is alive.)
+reserved(if) operator(()ident(posix_kill)operator(()local_variable($minion)operator(,) integer(0)operator(\))operator(\)) operator({)
+ pre_type(echo) delimiter(")local_variable($minion)string( is alive!)char(\\n)delimiter(")operator(;)
+operator(}) reserved(else) operator({)
+ pre_type(echo) delimiter(")local_variable($minion)string( is deceased.)char(\\n)delimiter(")operator(;)
+operator(})
+
+comment(// @@PLEAC@@_16.15)
+comment(// call got_sig_quit for every SIGQUIT)
+ident(pcntl_signal)operator(()constant(SIGQUIT)operator(,) delimiter(')string(got_sig_quit)delimiter(')operator(\))operator(;)
+comment(// call got_sig_pipe for every SIGPIPE)
+ident(pcntl_signal)operator(()constant(SIGPIPE)operator(,) delimiter(')string(got_sig_pipe)delimiter(')operator(\))operator(;)
+comment(// increment ouch for every SIGINT)
+pre_type(function) ident(got_sig_int)operator(()local_variable($signal)operator(\)) operator({) pre_type(global) local_variable($ouch)operator(;) local_variable($ouch)operator(++)operator(;) operator(})
+ident(pcntl_signal)operator(()constant(SIGINT)operator(,) delimiter(')string(got_sig_int)delimiter(')operator(\))operator(;)
+comment(// ignore the signal INT)
+ident(pcntl_signal)operator(()constant(SIGINT)operator(,) constant(SIG_IGN)operator(\))operator(;)
+comment(// restore default STOP signal handling)
+ident(pcntl_signal)operator(()constant(SIGSTOP)operator(,) constant(SIG_DFL)operator(\))operator(;)
+
+comment(// @@PLEAC@@_16.16)
+comment(// the signal handler)
+pre_type(function) ident(ding)operator(()local_variable($signal)operator(\)) operator({)
+ ident(fwrite)operator(()constant(STDERR)operator(,) delimiter(")string(\\)string(x07Enter your name!)char(\\n)delimiter(")operator(\))operator(;)
+operator(})
+
+comment(// prompt for name, overriding SIGINT)
+pre_type(function) ident(get_name)operator(()operator(\)) operator({)
+ reserved(declare)operator(()ident(ticks) operator(=) integer(1)operator(\))operator(;)
+ ident(pcntl_signal)operator(()constant(SIGINT)operator(,) delimiter(')string(ding)delimiter(')operator(\))operator(;)
+
+ pre_type(echo) delimiter(")string(Kindly Stranger, please enter your name: )delimiter(")operator(;)
+ reserved(while) operator(()operator(!)operator(@)ident(stream_select)operator(()local_variable($read)operator(=)pre_type(array)operator(()constant(STDIN)operator(\))operator(,)
+ local_variable($write)operator(=)pre_type(null)operator(,)
+ local_variable($except)operator(=)pre_type(null)operator(,)
+ integer(1)operator(\))operator(\)) operator({)
+ comment(// allow signals to be observed)
+ operator(})
+ local_variable($name) operator(=) ident(fgets)operator(()constant(STDIN)operator(\))operator(;)
+
+ comment(// Since pcntl_signal(\) doesn't return the old signal handler, the)
+ comment(// best we can do here is set it back to the default behavior.)
+ ident(pcntl_signal)operator(()constant(SIGINT)operator(,) constant(SIG_DFL)operator(\))operator(;)
+
+ reserved(return) local_variable($name)operator(;)
+operator(})
+
+comment(// @@PLEAC@@_16.17)
+pre_type(function) ident(got_int)operator(()local_variable($signal)operator(\)) operator({)
+ ident(pcntl_signal)operator(()constant(SIGINT)operator(,) delimiter(')string(got_int)delimiter(')operator(\))operator(;) comment(// but not for SIGCHLD!)
+ comment(// ...)
+operator(})
+ident(pcntl_signal)operator(()constant(SIGINT)operator(,) delimiter(')string(got_int)delimiter(')operator(\))operator(;)
+
+comment(// -----------------------------)
+
+reserved(declare)operator(()ident(ticks) operator(=) integer(1)operator(\))operator(;)
+local_variable($interrupted) operator(=) pre_type(false)operator(;)
+
+pre_type(function) ident(got_int)operator(()local_variable($signal)operator(\)) operator({)
+ pre_type(global) local_variable($interrupted)operator(;)
+ local_variable($interrupted) operator(=) pre_type(true)operator(;)
+ comment(// The third argument to pcntl_signal(\) determines if system calls)
+ comment(// should be restarted after a signal. It defaults to true.)
+ ident(pcntl_signal)operator(()constant(SIGINT)operator(,) delimiter(')string(got_int)delimiter(')operator(,) pre_type(false)operator(\))operator(;) comment(// or SIG_IGN)
+operator(})
+ident(pcntl_signal)operator(()constant(SIGINT)operator(,) delimiter(')string(got_int)delimiter(')operator(,) pre_type(false)operator(\))operator(;)
+
+comment(// ... long-running code that you don't want to restart)
+
+reserved(if) operator(()local_variable($interrupted)operator(\)) operator({)
+ comment(// deal with the signal)
+operator(})
+
+comment(// @@PLEAC@@_16.18)
+comment(// ignore signal INT)
+ident(pcntl_signal)operator(()constant(SIGINT)operator(,) constant(SIG_IGN)operator(\))operator(;)
+
+comment(// install signal handler)
+reserved(declare)operator(()ident(ticks) operator(=) integer(1)operator(\))operator(;)
+pre_type(function) ident(tsktsk)operator(()local_variable($signal)operator(\)) operator({)
+ ident(fwrite)operator(()constant(STDERR)operator(,) delimiter(")string(\\)string(x07The long habit of living indisposeth us for dying.)delimiter(")operator(\))operator(;)
+ ident(pcntl_signal)operator(()constant(SIGINT)operator(,) delimiter(')string(tsktsk)delimiter(')operator(\))operator(;)
+operator(})
+ident(pcntl_signal)operator(()constant(SIGINT)operator(,) delimiter(')string(tsktsk)delimiter(')operator(\))operator(;)
+
+comment(// @@PLEAC@@_16.19)
+ident(pcntl_signal)operator(()constant(SIGCHLD)operator(,) constant(SIG_IGN)operator(\))operator(;)
+
+comment(// -----------------------------)
+
+reserved(declare)operator(()ident(ticks) operator(=) integer(1)operator(\))operator(;)
+pre_type(function) ident(reaper)operator(()local_variable($signal)operator(\)) operator({)
+ local_variable($pid) operator(=) ident(pcntl_waitpid)operator(()integer(-1)operator(,) local_variable($status)operator(,) constant(WNOHANG)operator(\))operator(;)
+ reserved(if) operator(()local_variable($pid) operator(>) integer(0)operator(\)) operator({)
+ comment(// ...)
+ ident(reaper)operator(()local_variable($signal)operator(\))operator(;)
+ operator(})
+ comment(// install *after* calling waitpid)
+ ident(pcntl_signal)operator(()constant(SIGCHLD)operator(,) delimiter(')string(reaper)delimiter(')operator(\))operator(;)
+operator(})
+ident(pcntl_signal)operator(()constant(SIGCHLD)operator(,) delimiter(')string(reaper)delimiter(')operator(\))operator(;)
+
+comment(// -----------------------------)
+
+reserved(declare)operator(()ident(ticks) operator(=) integer(1)operator(\))operator(;)
+pre_type(function) ident(reaper)operator(()local_variable($signal)operator(\)) operator({)
+ local_variable($pid) operator(=) ident(pcntl_waitpid)operator(()integer(-1)operator(,) local_variable($status)operator(,) constant(WNOHANG)operator(\))operator(;)
+ reserved(if) operator(()local_variable($pid) operator(==) integer(-1)operator(\)) operator({)
+ comment(// No child waiting. Ignore it.)
+ operator(}) reserved(else) operator({)
+ reserved(if) operator(()ident(pcntl_wifexited)operator(()local_variable($signal)operator(\))operator(\)) operator({)
+ pre_type(echo) delimiter(")string(Process )local_variable($pid)string( exited.)char(\\n)delimiter(")operator(;)
+ operator(}) reserved(else) operator({)
+ pre_type(echo) delimiter(")string(False alarm on )local_variable($pid)char(\\n)delimiter(")operator(;)
+ operator(})
+ ident(reaper)operator(()local_variable($signal)operator(\))operator(;)
+ operator(})
+ ident(pcntl_signal)operator(()constant(SIGCHLD)operator(,) delimiter(')string(reaper)delimiter(')operator(\))operator(;)
+operator(})
+ident(pcntl_signal)operator(()constant(SIGCHLD)operator(,) delimiter(')string(reaper)delimiter(')operator(\))operator(;)
+
+comment(// @@PLEAC@@_16.20)
+comment(// PHP does not support sigprocmask(\).)
+
+comment(// @@PLEAC@@_16.21)
+reserved(declare)operator(()ident(ticks) operator(=) integer(1)operator(\))operator(;)
+local_variable($aborted) operator(=) pre_type(false)operator(;)
+
+pre_type(function) ident(handle_alarm)operator(()local_variable($signal)operator(\)) operator({)
+ pre_type(global) local_variable($aborted)operator(;)
+ local_variable($aborted) operator(=) pre_type(true)operator(;)
+operator(})
+ident(pcntl_signal)operator(()constant(SIGALRM)operator(,) delimiter(')string(handle_alarm)delimiter(')operator(\))operator(;)
+
+ident(pcntl_alarm)operator(()integer(3600)operator(\))operator(;)
+comment(// long-time operations here)
+ident(pcntl_alarm)operator(()integer(0)operator(\))operator(;)
+reserved(if) operator(()local_variable($aborted)operator(\)) operator({)
+ comment(// timed out - do what you will here)
+operator(})
diff --git a/test/scanners/php/pleac.in.php b/test/scanners/php/pleac.in.php
new file mode 100644
index 0000000..4bd0300
--- /dev/null
+++ b/test/scanners/php/pleac.in.php
@@ -0,0 +1,5516 @@
+# -*- php -*-
+# The examples are taken from the Perl Cookbook
+# By Tom Christiansen & Nathan Torkington
+# see http://www.oreilly.com/catalog/cookbook for more
+
+# @@PLEAC@@_NAME
+# @@SKIP@@ PHP
+
+# @@PLEAC@@_WEB
+# @@SKIP@@ http://php.net/
+
+# @@PLEAC@@_1.0
+#-----------------------------
+$string = '\n'; # two characters, \ and an n
+$string = 'Jon \'Maddog\' Orwant'; # literal single quotes
+$string = 'Jon "Maddog" Orwant'; # literal double quotes
+#-----------------------------
+$string = "\n"; # a "newline" character
+$string = "Jon \"Maddog\" Orwant"; # literal double quotes
+$string = "Jon 'Maddog' Orwant"; # literal single quotes
+#-----------------------------
+$a =
+"This is a multiline
+here document";
+
+$a = <<<EOF
+This is a multiline here document
+terminated by EOF on a line by itself
+EOF;
+#-----------------------------
+
+# @@PLEAC@@_1.1
+#-----------------------------
+$value = substr($string, $offset, $count);
+$value = substr($string, $offset);
+
+$string = substr_replace($string, $newstring, $offset, $count);
+$string = substr_replace($string, $newtail, $offset);
+#-----------------------------
+# get a 5-byte string, skip 3, then grab 2 8-byte strings, then the rest
+list($leading, $s1, $s2, $trailing) =
+ array_values(unpack("A5a/x3/A8b/A8c/A*d", $data);
+
+# split at five byte boundaries
+preg_match_all ("/.{5}/", $data, $f, PREG_PATTERN_ORDER);
+$fivers = $f[0];
+
+# chop string into individual characters
+$chars = $string;
+#-----------------------------
+$string = "This is what you have";
+# +012345678901234567890 Indexing forwards (left to right)
+# 109876543210987654321- Indexing backwards (right to left)
+# note that 0 means 10 or 20, etc. above
+
+$first = substr($string, 0, 1); # "T"
+$start = substr($string, 5, 2); # "is"
+$rest = substr($string, 13); # "you have"
+$last = substr($string, -1); # "e"
+$end = substr($string, -4); # "have"
+$piece = substr($string, -8, 3); # "you"
+#-----------------------------
+$string = "This is what you have";
+print $string;
+#This is what you have
+
+$string = substr_replace($string, "wasn't", 5, 2); # change "is" to "wasn't"
+#This wasn't what you have
+
+$string = substr_replace($string, "ondrous", -12); # "This wasn't wondrous"
+#This wasn't wondrous
+
+$string = substr_replace($string, "", 0, 1); # delete first character
+#his wasn't wondrous
+
+$string = substr_replace($string, "", -10); # delete last 10 characters
+#his wasn'
+#-----------------------------
+if (preg_match("/pattern/", substr($string, -10)) {
+ print "Pattern matches in last 10 characters\n";
+}
+
+# substitute "at" for "is", restricted to first five characters
+$string=(substr_replace(preg_replace("/is/", "at", substr($string,0,5)),0,5);
+#-----------------------------
+# exchange the first and last letters in a string
+$a = "make a hat";
+list($a[0], $a[strlen($a)-1]) = Array(substr($a,-1), substr($a,0,1));
+print $a;
+
+#-----------------------------
+# extract column with unpack
+$a = "To be or not to be";
+$b = unpack("x6/A6a", $a); # skip 6, grab 6
+print $b['a'];
+
+
+$b = unpack("x6/A2b/X5/A2c", $a); # forward 6, grab 2; backward 5, grab 2
+print $b['b']."\n".$b['c']."\n";
+
+#-----------------------------
+function cut2fmt() {
+ $positions = func_get_args();
+ $template = '';
+ $lastpos = 1;
+ foreach($positions as $place) {
+ $template .= "A" . ($place - $lastpos) . " ";
+ $lastpos = $place;
+ }
+ $template .= "A*";
+ return $template;
+}
+
+$fmt = cut2fmt(8, 14, 20, 26, 30);
+print "$fmt\n";
+#A7 A6 A6 A6 A4 A*
+#-----------------------------
+
+# @@PLEAC@@_1.2
+#-----------------------------
+# use $b if $b is true, else $c
+$a = $b?$b:$c;
+
+# set $x to $y unless $x is already true
+$x || $x=$y;
+#-----------------------------
+# use $b if $b is defined, else $c
+$a = defined($b) ? $b : $c;
+#-----------------------------
+$foo = $bar || $foo = "DEFAULT VALUE";
+#-----------------------------
+$dir = array_shift($_SERVER['argv']) || $dir = "/tmp";
+#-----------------------------
+$dir = $_SERVER['argv'][0] || $dir = "/tmp";
+#-----------------------------
+$dir = defined($_SERVER['argv'][0]) ? array_shift($_SERVER['argv']) : "/tmp";
+#-----------------------------
+$dir = count($_SERVER['argv']) ? $_SERVER['argv'][0] : "/tmp";
+#-----------------------------
+$count[$shell?$shell:"/bin/sh"]++;
+#-----------------------------
+# find the user name on Unix systems
+$user = $_ENV['USER']
+ || $user = $_ENV['LOGNAME']
+ || $user = posix_getlogin()
+ || $user = posix_getpwuid(posix_getuid())[0]
+ || $user = "Unknown uid number $<";
+#-----------------------------
+$starting_point || $starting_point = "Greenwich";
+#-----------------------------
+count($a) || $a = $b; # copy only if empty
+$a = count($b) ? $b : $c; # assign @b if nonempty, else @c
+#-----------------------------
+
+# @@PLEAC@@_1.3
+#-----------------------------
+list($VAR1, $VAR2) = array($VAR2, $VAR1);
+#-----------------------------
+$temp = $a;
+$a = $b;
+$b = $temp;
+#-----------------------------
+$a = "alpha";
+$b = "omega";
+list($a, $b) = array($b, $a); # the first shall be last -- and versa vice
+#-----------------------------
+list($alpha, $beta, $production) = Array("January","March","August");
+# move beta to alpha,
+# move production to beta,
+# move alpha to production
+list($alpha, $beta, $production) = array($beta, $production, $alpha);
+#-----------------------------
+
+# @@PLEAC@@_1.4
+#-----------------------------
+$num = ord($char);
+$char = chr($num);
+#-----------------------------
+$char = sprintf("%c", $num); # slower than chr($num)
+printf("Number %d is character %c\n", $num, $num);
+#-----------------------------
+$ASCII = unpack("C*", $string);
+eval('$STRING = pack("C*", '.implode(',',$ASCII).');');
+#-----------------------------
+$ascii_value = ord("e"); # now 101
+$character = chr(101); # now "e"
+#-----------------------------
+printf("Number %d is character %c\n", 101, 101);
+#-----------------------------
+$ascii_character_numbers = unpack("C*", "sample");
+print explode(" ",$ascii_character_numbers)."\n";
+
+eval('$word = pack("C*", '.implode(',',$ascii_character_numbers).');');
+$word = pack("C*", 115, 97, 109, 112, 108, 101); # same
+print "$word\n";
+#-----------------------------
+$hal = "HAL";
+$ascii = unpack("C*", $hal);
+foreach ($ascii as $val) {
+ $val++; # add one to each ASCII value
+}
+eval('$ibm = pack("C*", '.implode(',',$ascii).');');
+print "$ibm\n"; # prints "IBM"
+#-----------------------------
+
+# @@PLEAC@@_1.5
+#-----------------------------
+// using perl regexp
+$array = preg_split('//', $string ,-1, PREG_SPLIT_NO_EMPTY);
+// using PHP function: $array = str_split($string);
+
+// Cannot use unpack with a format of 'U*' in PHP.
+#-----------------------------
+for ($offset = 0; preg_match('/(.)/', $string, $matches, 0, $offset) > 0; $offset++) {
+ // $matches[1] has charcter, ord($matches[1]) its number
+}
+#-----------------------------
+$seen = array();
+$string = "an apple a day";
+foreach (str_split($string) as $char) {
+ $seen[$char] = 1;
+}
+$keys = array_keys($seen);
+sort($keys);
+print "unique chars are: " . implode('', $keys)) . "\n";
+unique chars are: adelnpy
+#-----------------------------
+$seen = array();
+$string = "an apple a day";
+for ($offset = 0; preg_match('/(.)/', $string, $matches, 0, $offset) > 0; $offset++) {
+ $seen[$matches[1]] = 1;
+}
+$keys = array_keys($seen);
+sort($keys);
+print "unique chars are: " . implode('', $keys) . "\n";
+unique chars are: adelnpy
+#-----------------------------
+$sum = 0;
+foreach (unpack("C*", $string) as $byteval) {
+ $sum += $byteval;
+}
+print "sum is $sum\n";
+// prints "1248" if $string was "an apple a day"
+#-----------------------------
+$sum = array_sum(unpack("C*", $string));
+#-----------------------------
+
+// sum - compute 16-bit checksum of all input files
+$handle = @fopen($argv[1], 'r');
+$checksum = 0;
+while (!feof($handle)) {
+ $checksum += (array_sum(unpack("C*", fgets($handle))));
+}
+$checksum %= pow(2,16) - 1;
+print "$checksum\n";
+
+# @@INCLUDE@@ include/php/slowcat.php
+#-----------------------------
+
+# @@PLEAC@@_1.6
+#-----------------------------
+$revchars = strrev($string);
+#-----------------------------
+$revwords = implode(" ", array_reverse(explode(" ", $string)));
+#-----------------------------
+// reverse word order
+$string = 'Yoda said, "can you see this?"';
+$allwords = explode(" ", $string);
+$revwords = implode(" ", array_reverse($allwords));
+print $revwords . "\n";
+this?" see you "can said, Yoda
+#-----------------------------
+$revwords = implode(" ", array_reverse(explode(" ", $string)));
+#-----------------------------
+$revwords = implode(" ", array_reverse(preg_split("/(\s+)/", $string)));
+#-----------------------------
+$word = "reviver";
+$is_palindrome = ($word === strrev($word));
+#-----------------------------
+// quite a one-liner since "php" does not have a -n switch
+% php -r 'while (!feof(STDIN)) { $word = rtrim(fgets(STDIN)); if ($word == strrev($word) && strlen($word) > 5) print $word; }' < /usr/dict/words
+#-----------------------------
+
+# @@PLEAC@@_1.8
+#-----------------------------
+$text = preg_replace('/\$(\w+)/e', '$$1', $text);
+#-----------------------------
+list($rows, $cols) = Array(24, 80);
+$text = 'I am $rows high and $cols long';
+$text = preg_replace('/\$(\w+)/e', '$$1', $text);
+print $text;
+
+#-----------------------------
+$text = "I am 17 years old";
+$text = preg_replace('/(\d+)/e', '2*$1', $text);
+#-----------------------------
+# expand variables in $text, but put an error message in
+# if the variable isn't defined
+$text = preg_replace('/\$(\w+)/e','isset($$1)?$$1:\'[NO VARIABLE: $$1]\'', $text);
+#-----------------------------
+
+// As PHP arrays are used as hashes too, separation of section 4
+// and section 5 makes little sense.
+
+# @@PLEAC@@_1.9
+#-----------------------------
+$big = strtoupper($little);
+$little = strtolower($big);
+// PHP does not have the\L and\U string escapes.
+#-----------------------------
+$big = ucfirst($little);
+$little = strtolower(substr($big, 0, 1)) . substr($big, 1);
+#-----------------------------
+$beast = "dromedary";
+// capitalize various parts of $beast
+$capit = ucfirst($beast); // Dromedar
+// PHP does not have the\L and\U string escapes.
+$capall = strtoupper($beast); // DROMEDAR
+// PHP does not have the\L and\U string escapes.
+$caprest = strtolower(substr($beast, 0, 1)) . substr(strtoupper($beast), 1); // dROMEDAR
+// PHP does not have the\L and\U string escapes.
+#-----------------------------
+// titlecase each word's first character, lowercase the rest
+$text = "thIS is a loNG liNE";
+$text = ucwords(strtolower($text));
+print $text;
+This Is A Long Line
+#-----------------------------
+if (strtoupper($a) == strtoupper($b)) { // or strcasecmp($a, $b) == 0
+ print "a and b are the same\n";
+}
+#-----------------------------
+# @@INCLUDE@@ include/php/randcap.php
+
+// % php randcap.php < genesis | head -9
+#-----------------------------
+
+# @@PLEAC@@_1.10
+#-----------------------------
+echo $var1 . func() . $var2; // scalar only
+#-----------------------------
+// PHP can only handle variable expression without operators
+$answer = "STRING ${[ VAR EXPR ]} MORE STRING";
+#-----------------------------
+$phrase = "I have " . ($n + 1) . " guanacos.";
+// PHP cannot handle the complex exression: ${\($n + 1)}
+#-----------------------------
+// Rest of Discussion is not applicable to PHP
+#-----------------------------
+// Interpolating functions not available in PHP
+#-----------------------------
+
+# @@PLEAC@@_1.11
+# @@INCOMPLETE@@
+# @@INCOMPLETE@@
+
+# @@PLEAC@@_1.12
+#-----------------------------
+$output = wordwrap($str, $width, $break, $cut);
+#-----------------------------
+# @@INCLUDE@@ include/php/wrapdemo.php
+#-----------------------------
+// merge multiple lines into one, then wrap one long line
+print wordwrap(str_replace("\n", " ", file_get_contents('php://stdin')));
+#-----------------------------
+while(!feof(STDIN)) {
+ print wordwrap(str_replace("\n", " ", stream_get_line(STDIN, 0, "\n\n")));
+ print "\n\n";
+}
+#-----------------------------
+
+# @@PLEAC@@_1.13
+#-----------------------------
+//backslash
+$var = preg_replace('/([CHARLIST])/', '\\\$1', $var);
+// double
+$var = preg_replace('/([CHARLIST])/', '$1$1', $var);
+#-----------------------------
+$var = preg_replace('/%/', '%%', $var);
+#-----------------------------
+$string = 'Mom said, "Don\'t do that."';
+$string = preg_replace('/([\'"])/', '\\\$1', $string);
+// in PHP you can also use the addslashes() function
+#-----------------------------
+$string = 'Mom said, "Don\'t do that."';
+$string = preg_replace('/([\'"])/', '$1$1', $string);
+#-----------------------------
+$string = preg_replace('/([^A-Z])/', '\\\$1', $string);
+#-----------------------------
+// PHP does not have the \Q and \E string metacharacters
+$string = "this is\\ a\\ test\\!";
+// PHP's quotemeta() function is not the same as perl's quotemeta() function
+$string = preg_replace('/(\W)/', '\\\$1', 'is a test!');
+#-----------------------------
+
+# @@PLEAC@@_1.14
+#-----------------------------
+$string = trim($string);
+#-----------------------------
+// print what's typed, but surrounded by > < symbols
+while (!feof(STDIN)) {
+ print ">" . substr(fgets(STDIN), 0, -1) . "<\n";
+}
+#-----------------------------
+$string = preg_replace('/\s+/', ' ', $string); // finally, collapse middle
+#-----------------------------
+$string = trim($string);
+$string = preg_replace('/\s+/', ' ', $string);
+#-----------------------------
+// 1. trim leading and trailing white space
+// 2. collapse internal whitespace to single space each
+function sub_trim($string) {
+ $string = trim($string);
+ $string = preg_replace('/\s+/', ' ', $string);
+ return $string;
+}
+#-----------------------------
+
+# @@PLEAC@@_1.15
+# @@INCOMPLETE@@
+# @@INCOMPLETE@@
+
+# @@PLEAC@@_1.16
+#-----------------------------
+$code = soundex($string);
+#-----------------------------
+$phoned_words = metaphone("Schwern");
+#-----------------------------
+// substitution function for getpwent():
+// returns an array of user entries,
+// each entry contains the username and the full name
+function getpwent() {
+ $pwents = array();
+ $handle = fopen("passwd", "r");
+ while (!feof($handle)) {
+ $line = fgets($handle);
+ if (preg_match("/^#/", $line)) continue;
+ $cols = explode(":", $line);
+ $pwents[$cols[0]] = $cols[4];
+ }
+ return $pwents;
+}
+
+print "Lookup user: ";
+$user = rtrim(fgets(STDIN));
+if (empty($user)) exit;
+$name_code = soundex($user);
+$pwents = getpwent();
+foreach($pwents as $username => $fullname) {
+ preg_match("/(\w+)[^,]*\b(\w+)/", $fullname, $matches);
+ list(, $firstname, $lastname) = $matches;
+
+ if ($name_code == soundex($username) ||
+ $name_code == soundex($lastname) ||
+ $name_code == soundex($firstname))
+ {
+ printf("%s: %s %s\n", $username, $firstname, $lastname);
+ }
+}
+#-----------------------------
+
+# @@PLEAC@@_1.17
+#-----------------------------
+# @@INCLUDE@@ include/php/fixstyle.php
+#-----------------------------
+# @@INCLUDE@@ include/php/fixstyle2.php
+#-----------------------------
+// very fast, but whitespace collapse
+while (!feof($input)) {
+ $i = 0;
+ preg_match("/^(\s*)(.*)/", fgets($input), $matches); // emit leading whitespace
+ fwrite($output, $matches[1]);
+ foreach (preg_split("/(\s+)/", $matches[2]) as $token) { // preserve trailing whitespace
+ fwrite($output, (array_key_exists($token, $config) ? $config[$token] : $token) . " ");
+ }
+ fwrite($output, "\n");
+}
+#-----------------------------
+
+// @@PLEAC@@_2.0
+// As is the case under so many other languages floating point use under PHP is fraught
+// with dangers. Although the basic techniques shown below are valid, please refer to
+// the official PHP documentation for known issues, bugs, and alternate approaches
+
+// @@PLEAC@@_2.1
+// Two basic approaches to numeric validation:
+// * Built-in functions like 'is_numeric', 'is_int', 'is_float' etc
+// * Regexes, as shown below
+
+$s = '12.345';
+
+preg_match('/\D/', $s) && die("has nondigits\n");
+preg_match('/^\d+$/', $s) || die("not a natural number\n");
+preg_match('/^-?\d+$/', $s) || die("not an integer\n");
+preg_match('/^[+-]?\d+$/', $s) || die("not an integer\n");
+preg_match('/^-?\d+\.?\d*$/', $s) || die("not a decimal\n");
+preg_match('/^-?(?:\d+(?:\.\d*)?|\.\d+)$/', $s) || die("not a decimal\n");
+preg_match('/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/', $s) || die("not a C float\n");
+
+// ----------------------------
+
+function getnum($s)
+{
+ sscanf($s, "%D", $number); return isset($number) ? $number : 0;
+}
+
+echo getnum(123) . "\n"; // ok
+echo getnum(0xff) . "\n"; // ..
+echo getnum(044) . "\n"; // ..
+
+echo getnum('x') . "\n"; // fail
+
+// @@PLEAC@@_2.2
+// In PHP floating point comparisions are 'safe' [meaning the '==' comparison operator
+// can be used] as long as the value consists of 14 digits or less [total digits, either
+// side of the decimal point e.g. xxxxxxx.xxxxxxx, xxxxxxxxxxxxxx., .xxxxxxxxxxxxxx]. If
+// values with more digits must be compared, then:
+//
+// * Represent as strings, and take care to avoid any implicit conversions e.g. don't pass
+// a float as a float to a function and expect all digits to be retained - they won't be -
+// then use 'strcmp' to compare the strings
+//
+// * Avoid float use; perhaps use arbitrary precision arithmetic. In this case, the
+// 'bccomp' function is relevant
+
+// Will work as long as each floating point value is 14 digits or less
+if ($float_1 == $float_2)
+{
+ ; // ...
+}
+
+// Compare as strings
+$cmp = strcmp('123456789.123456789123456789', '123456789.123456789123456788');
+
+// Use 'bccomp'
+$precision = 5; // Number of significant comparison digits after decimal point
+if (bccomp('1.111117', '1.111116', $precision))
+{
+ ; // ...
+}
+
+$precision = 6;
+if (bccomp('1.111117', '1.111116', $precision))
+{
+ ; // ...
+}
+
+// ----------------------------
+
+$wage = 536;
+$week = $wage * 40;
+printf("One week's wage is: $%.2f\n", $week / 100);
+
+// @@PLEAC@@_2.3
+// Preferred approach
+$rounded = round($unrounded, $precision);
+
+// Possible alternate approach
+$format = '%[width].[prec]f';
+$rounded = sprintf($format, $unrounded);
+
+// ------------
+
+$a = 0.255; $b = round($a, 2);
+echo "Unrounded: {$a}\nRounded: {$b}\n";
+
+$a = 0.255; $b = sprintf('%.2f', $a);
+echo "Unrounded: {$a}\nRounded: {$b}\n";
+
+$a = 0.255;
+printf("Unrounded: %.f\nRounded: %.2f\n", $a, $a);
+
+// ----------------------------
+
+echo "number\tint\tfloor\tceil\n";
+
+foreach(array(3.3, 3.5, 3.7, -3.3) as $number)
+{
+ printf("%.1f\t%.1f\t%.1f\t%.1f\n", $number, (int) $number, floor($number), ceil($number));
+}
+
+// @@PLEAC@@_2.4
+// PHP offers the 'bindec' and 'decbin' functions to converting between binary and decimal
+
+$num = bindec('0110110');
+
+$binstr = decbin(54);
+
+// @@PLEAC@@_2.5
+foreach (range($X, $Y) as $i)
+{
+ ; // ...
+}
+
+foreach (range($X, $Y, 7) as $i)
+{
+ ; // ...
+}
+
+for ($i = $X; $i <= $Y; $i++)
+{
+ ; // ...
+}
+
+for ($i = $X; $i <= $Y; $i += 7)
+{
+ ; // ...
+}
+
+// ----------------------------
+
+echo 'Infancy is:'; foreach(range(0, 2) as $i) echo " {$i}\n";
+echo 'Toddling is:'; foreach(range(3, 4) as $i) echo " {$i}\n";
+echo 'Childhood is:'; foreach(range(5, 12) as $i) echo " {$i}\n";
+
+// @@PLEAC@@_2.6
+// PHP offers no native support for Roman Numerals. However, a 'Numbers_Roman' class
+// is available for download from PEAR: [http://pear.php.net/package/Numbers_Roman].
+// Note the following 'include' directives are required:
+//
+// include_once('Numbers/Roman.php');
+
+$roman = Numbers_Roman::toNumeral($arabic);
+$arabic = Numbers_Roman::toNumber($roman);
+
+// ----------------------------
+
+$roman_fifteen = Numbers_Roman::toNumeral(15);
+
+$arabic_fifteen = Numbers_Roman::toNumber($roman_fifteen);
+
+printf("Roman for fifteen is: %s\n", $roman_fifteen);
+printf("Arabic for fifteen is: %d\n", $arabic_fifteen);
+
+// @@PLEAC@@_2.7
+// Techniques used here simply mirror Perl examples, and are not an endorsement
+// of any particular RNG technique
+
+// In PHP do this ...
+$random = rand($lowerbound, $upperbound);
+$random = rand($x, $y);
+
+// ----------------------------
+
+function make_password($chars, $reqlen)
+{
+ $len = strlen($chars);
+ for ($i = 0; $i < $reqlen; $i++) $password .= substr($chars, rand(0, $len), 1);
+ return $password;
+}
+
+$chars = 'ABCDEfghijKLMNOpqrstUVWXYz'; $reqlen = 8;
+
+$password = make_password($chars, $reqlen);
+
+// @@PLEAC@@_2.8
+// PHP sports a large number of C Standard Library routines including the 'srand'
+// function, used to re-seed the RNG used with calls to the 'rand' function. Thus,
+// as per Perl example:
+
+while (TRUE)
+{
+ $seed = (int) fgets(STDIN);
+ if (!empty($seed)) break;
+}
+
+srand($seed);
+
+// @@PLEAC@@_2.9
+// The above is considered - for many reasons - a poor way of seeding the RNG. PHP
+// also offers alternate versions of the functions, 'mt_srand' and 'mt_rand',
+// which are described as faster, and more 'random', though key to obtaining a
+// more 'random' distribution of generated numbers seems to be through using
+// a combination of a previously saved random value in combination with an
+// unrepeatable value [like the current time in microseconds] that is multiplied
+// by a large prime number, or perhaps as part of a hash [examples available in
+// PHP documentation for 'srand' and 'mt_srand']
+
+mt_srand($saved_random_value + microtime() * 1000003);
+
+// or
+
+mt_srand(($saved_random_value + hexdec(substr(md5(microtime()), -8))) & 0x7fffffff);
+
+// Use of 'mt_rand' together with an appropriate seeding approach should help better
+// approximate the generation of a 'truly random value'
+$truly_random_value = mt_rand();
+
+// @@PLEAC@@_2.10
+function random() { return (float) rand() / (float) getrandmax(); }
+
+function gaussian_rand()
+{
+ $u1 = 0.0; $u2 = 0.0; $g1 = 0.0; $g2 = 0.0; $w = 0.0;
+
+ do
+ {
+ $u1 = 2.0 * random() - 1.0; $u2 = 2.0 * random() - 1.0;
+ $w = $u1 * $u1 + $u2 * $u2;
+ } while ($w > 1.0);
+
+ $w = sqrt((-2.0 * log($w)) / $w); $g2 = $u1 * $w; $g1 = $u2 * $w;
+
+ return $g1;
+}
+
+// ------------
+
+$mean = 25.0; $sdev = 2.0;
+$salary = gaussian_rand() * $mean + $sdev;
+
+printf("You have been hired at: %.2f\n", $salary);
+
+// @@PLEAC@@_2.11
+// 'deg2rad' and 'rad2deg' are actually PHP built-ins, but here is how you might implement
+/ them if needed
+function deg2rad_($deg) { return ($deg / 180.0) * M_PI; }
+function rad2deg_($rad) { return ($rad / M_PI) * 180.0; }
+
+// ------------
+
+printf("%f\n", deg2rad_(180.0));
+printf("%f\n", deg2rad(180.0));
+
+// ----------------------------
+
+function degree_sin($deg) { return sin(deg2rad($deg)); }
+
+// ------------
+
+$rad = deg2rad(380.0);
+
+printf("%f\n", sin($rad));
+printf("%f\n", degree_sin(380.0));
+
+// @@PLEAC@@_2.12
+function my_tan($theta) { return sin($theta) / cos($theta); }
+
+// ------------
+
+$theta = 3.7;
+
+printf("%f\n", my_tan($theta));
+printf("%f\n", tan($theta));
+
+// @@PLEAC@@_2.13
+$value = 100.0;
+
+$log_e = log($value);
+$log_10 = log10($value);
+
+// ----------------------------
+
+function log_base($base, $value) { return log($value) / log($base); }
+
+// ------------
+
+$answer = log_base(10.0, 10000.0);
+
+printf("log(10, 10,000) = %f\n", $answer);
+
+// @@PLEAC@@_2.14
+// PHP offers no native support for matrices. However, a 'Math_Matrix' class
+// is available for download from PEAR: [http://pear.php.net/package/Math_Matrix].
+// Note the following 'include' directives are required:
+//
+// include_once('Math/Matrix.php');
+
+$a = new Math_Matrix(array(array(3, 2, 3), array(5, 9, 8)));
+$b = new Math_Matrix(array(array(4, 7), array(9, 3), array(8, 1)));
+
+echo $a->toString() . "\n";
+echo $b->toString() . "\n";
+
+// NOTE: When I installed this package I had to rename the 'clone' method else
+// it would not load, so I chose to rename it to 'clone_', and this usage is
+// shown below. This bug may well be fixed by the time you obtain this package
+
+$c = $a->clone_();
+$c->multiply($b);
+
+echo $c->toString() . "\n";
+
+// @@PLEAC@@_2.15
+// PHP offers no native support for complex numbers. However, a 'Math_Complex' class
+// is available for download from PEAR: [http://pear.php.net/package/Math_Complex].
+// Note the following 'include' directives are required:
+//
+// include_once('Math/Complex.php');
+// include_once('Math/TrigOp.php');
+// include_once('Math/ComplexOp.php');
+
+$a = new Math_Complex(3, 5);
+$b = new Math_Complex(2, -2);
+
+$c = Math_ComplexOp::mult($a, $b);
+
+echo $c->toString() . "\n";
+
+// ----------------------------
+
+$d = new Math_Complex(3, 4);
+$r = Math_ComplexOp::sqrt($d);
+
+echo $r->toString() . "\n";
+
+// @@PLEAC@@_2.16
+// Like C, PHP supports decimal-alternate notations. Thus, for example, the integer
+// value, 867, is expressable in literal form as:
+//
+// Hexadecimal -> 0x363
+// Octal -> 01543
+//
+// For effecting such conversions using strings there is 'sprintf' and 'sscanf'.
+
+$dec = 867;
+$hex = sprintf('%x', $dec);
+$oct = sprintf('%o', $dec);
+
+// ------------
+
+$dec = 0;
+$hex = '363';
+
+sscanf($hex, '%x', $dec);
+
+// ------------
+
+$dec = 0;
+$oct = '1543';
+
+sscanf($oct, '%o', $dec);
+
+// ----------------------------
+
+$number = 0;
+
+printf('Gimme a number in decimal, octal, or hex: ');
+sscanf(fgets(STDIN), '%D', $number);
+
+printf("%d %x %o\n", $number, $number, $number);
+
+// @@PLEAC@@_2.17
+// PHP offers the 'number_format' built-in function to, among many other format tasks,
+// commify numbers. Perl-compatible [as well as extended] regexes are also available
+
+function commify_series($s) { return number_format($s, 0, '', ','); }
+
+// ------------
+
+$hits = 3456789;
+
+printf("Your website received %s accesses last month\n", commify_series($hits));
+
+// ----------------------------
+
+function commify($s)
+{
+ return strrev(preg_replace('/(\d\d\d)(?=\d)(?!\d*\.)/', '${1},', strrev($s)));
+}
+
+// ------------
+
+$hits = 3456789;
+
+echo commify(sprintf("Your website received %d accesses last month\n", $hits));
+
+// @@PLEAC@@_2.18
+function pluralise($value, $root, $singular='' , $plural='s')
+{
+ return $root . (($value > 1) ? $plural : $singular);
+}
+
+// ------------
+
+$duration = 1;
+printf("It took %d %s\n", $duration, pluralise($duration, 'hour'));
+printf("%d %s %s enough.\n", $duration, pluralise($duration, 'hour'),
+ pluralise($duration, '', 'is', 'are'));
+
+$duration = 5;
+printf("It took %d %s\n", $duration, pluralise($duration, 'hour'));
+printf("%d %s %s enough.\n", $duration, pluralise($duration, 'hour'),
+ pluralise($duration, '', 'is', 'are'));
+
+// ----------------------------
+
+function plural($singular)
+{
+ $s2p = array('/ss$/' => 'sses', '/([psc]h)$/' => '${1}es', '/z$/' => 'zes',
+ '/ff$/' => 'ffs', '/f$/' => 'ves', '/ey$/' => 'eys',
+ '/y$/' => 'ies', '/ix$/' => 'ices', '/([sx])$/' => '$1es',
+ '$' => 's');
+
+ foreach($s2p as $s => $p)
+ {
+ if (preg_match($s, $singular)) return preg_replace($s, $p, $singular);
+ }
+}
+
+// ------------
+
+foreach(array('mess', 'index', 'leaf', 'puppy') as $word)
+{
+ printf("%6s -> %s\n", $word, plural($word));
+}
+
+// @@PLEAC@@_2.19
+// @@INCOMPLETE@@
+// @@INCOMPLETE@@
+
+// @@PLEAC@@_3.0
+// PHP's date / time suport is quite extensive, and appears grouped into three areas of
+// functionality:
+//
+// * UNIX / C Library [libc]-based routines, which include [among others]:
+// - localtime, gmtime
+// - strftime, strptime, mktime
+// - time, getdate, gettimeofday,
+//
+// * PHP 'native' functions, those date / time routines released in earlier versions,
+// and which otherwise provide 'convenience' functionality; these include:
+// - date
+// - strtotime
+//
+// * 'DateTime' class-based. This facility appears [according to the PHP documentation]
+// to be extremely new / experimental, so whilst usage examples will be provided, they
+// should not be taken to be 'official' examples, and obviously, subject to change.
+// My own impression is that this facility is currently only partially implemented,
+// so there is limited use for these functions. The functions included in this group
+// are some of the 'date_'-prefixed functions; they are, however, not used standalone,
+// but as methods in conjunction with an object. Typical usage:
+//
+// $today = new DateTime(); // actually calls: date_create($today, ...);
+// echo $today->format('U') . "\n"; // actually calls: date_format($today, ...);
+//
+// Also worth mentioning is the PEAR [PHP Extension and Repository] package, 'Calendar',
+// which offers a rich set of date / time manipulation facilities. However, since it is
+// not currently shipped with PHP, no examples appear
+
+// Helper functions for performing date arithmetic
+
+function dateOffset()
+{
+ static $tbl = array('sec' => 1, 'min' => 60, 'hou' => 3600, 'day' => 86400, 'wee' => 604800);
+ $delta = 0;
+
+ foreach (func_get_args() as $arg)
+ {
+ $kv = explode('=', $arg);
+ $delta += $kv[1] * $tbl[strtolower(substr($kv[0], 0, 3))];
+ }
+
+ return $delta;
+}
+
+function dateInterval($intvltype, $timevalue)
+{
+ static $tbl = array('sec' => 1, 'min' => 60, 'hou' => 3600, 'day' => 86400, 'wee' => 604800);
+ return (int) round($timevalue / $tbl[strtolower(substr($intvltype, 0, 3))]);
+}
+
+// ----------------------------
+
+// Extract indexed array from 'getdate'
+$today = getdate();
+printf("Today is day %d of the current year\n", $today['yday']);
+
+// Extract indexed, and associative arrays, respectively, from 'localtime'
+$today = localtime();
+printf("Today is day %d of the current year\n", $today[7]);
+
+$today = localtime(time(), TRUE);
+printf("Today is day %d of the current year\n", $today['tm_yday']);
+
+// @@PLEAC@@_3.1
+define(SEP, '-');
+
+// ------------
+
+$today = getdate();
+
+$day = $today['mday'];
+$month = $today['mon'];
+$year = $today['year'];
+
+// Either do this to use interpolation:
+$sep = SEP;
+echo "Current date is: {$year}{$sep}{$month}{$sep}{$day}\n";
+
+// or simply concatenate:
+echo 'Current date is: ' . $year . SEP . $month . SEP . $day . "\n";
+
+// ------------
+
+$today = localtime(time(), TRUE);
+
+$day = $today['tm_mday'];
+$month = $today['tm_mon'] + 1;
+$year = $today['tm_year'] + 1900;
+
+printf("Current date is: %4d%s%2d%s%2d\n", $year, SEP, $month, SEP, $day);
+
+// ------------
+
+$format = 'Y' . SEP . 'n' . SEP . 'd';
+
+$today = date($format);
+
+echo "Current date is: {$today}\n";
+
+// ------------
+
+$sep = SEP;
+
+$today = strftime("%Y$sep%m$sep%d");
+
+echo "Current date is: {$today}\n";
+
+// @@PLEAC@@_3.2
+$timestamp = mktime($hour, $min, $sec, $month, $day, $year);
+
+$timestamp = gmmktime($hour, $min, $sec, $month, $day, $year);
+
+// @@PLEAC@@_3.3
+$dmyhms = getdate(); // timestamp: current date / time
+
+$dmyhms = getdate($timestamp); // timestamp: arbitrary
+
+$day = $dmyhms['mday'];
+$month = $dmyhms['mon'];
+$year = $dmyhms['year'];
+
+$hours = $dmyhms['hours'];
+$minutes = $dmyhms['minutes'];
+$seconds = $dmyhms['seconds'];
+
+// @@PLEAC@@_3.4
+// Date arithmetic is probably most easily performed using timestamps [i.e. *NIX Epoch
+// Seconds]. Dates - in whatever form - are converted to timestamps, these are
+// arithmetically manipulated, and the result converted to whatever form required.
+// Note: use 'mktime' to create timestamps properly adjusted for daylight saving; whilst
+// 'strtotime' is more convenient to use, it does not, AFAIK, include this adjustment
+
+$when = $now + $difference;
+$then = $now - $difference;
+
+// ------------
+
+$now = mktime(0, 0, 0, 8, 6, 2003);
+
+$diff1 = dateOffset('day=1'); $diff2 = dateOffset('weeks=2');
+
+echo 'Today is: ' . date('Y-m-d', $now) . "\n";
+echo 'One day in the future is: ' . date('Y-m-d', $now + $diff1) . "\n";
+echo 'Two weeks in the past is: ' . date('Y-m-d', $now - $diff2) . "\n";
+
+// ----------------------------
+
+// Date arithmetic performed using a custom function, 'dateOffset'. Internally, offset may
+// be computed in one of several ways:
+// * Direct timestamp manipulation - fastest, but no daylight saving adjustment
+// * Via 'date' built-in function - slower [?], needs a base time from which to
+// compute values, but has daylight saving adjustment
+// * Via 'strtotime' built-in function - as for 'date'
+// * Via 'DateTime' class
+//
+// Approach used here is to utilise direct timestamp manipulation in 'dateOffset' [it's
+// performance can also be improved by replacing $tbl with a global definition etc],
+// and to illustrate how the other approaches might be used
+
+// 1. 'dateOffset'
+
+$birthtime = mktime(3, 45, 50, 1, 18, 1973);
+
+$interval = dateOffset('day=55', 'hours=2', 'min=17', 'sec=5');
+
+$then = $birthtime + $interval;
+
+printf("Birthtime is: %s\nthen is: %s\n", date(DATE_RFC1123, $birthtime), date(DATE_RFC1123, $then));
+
+// ------------
+
+// 2. 'date'
+
+// Base values, and offsets, respectively
+$hr = 3; $min = 45; $sec = 50; $mon = 1; $day = 18; $year = 1973;
+
+$yroff = 0; $monoff = 0; $dayoff = 55; $hroff = 2; $minoff = 17; $secoff = 5;
+
+// Base date
+$birthtime = mktime($hr, $min, $sec, $mon, $day, $year, TRUE);
+
+$year = date('Y', $birthtime) + $yroff;
+$mon = date('m', $birthtime) + $monoff;
+$day = date('d', $birthtime) + $dayoff;
+
+$hr = date('H', $birthtime) + $hroff;
+$min = date('i', $birthtime) + $minoff;
+$sec = date('s', $birthtime) + $secoff;
+
+// Offset date
+$then = mktime($hr, $min, $sec, $mon, $day, $year, TRUE);
+
+printf("Birthtime is: %s\nthen is: %s\n", date(DATE_RFC1123, $birthtime), date(DATE_RFC1123, $then));
+
+// ------------
+
+// 3. 'strtotime'
+
+// Generate timestamp whatever way is preferable
+$birthtime = mktime(3, 45, 50, 1, 18, 1973);
+$birthtime = strtotime('1/18/1973 03:45:50');
+
+$then = strtotime('+55 days 2 hours 17 minutes 2 seconds', $birthtime);
+
+printf("Birthtime is: %s\nthen is: %s\n", date(DATE_RFC1123, $birthtime), date(DATE_RFC1123, $then));
+
+// ------------
+
+// 4. 'DateTime' class
+
+$birthtime = new DateTime('1/18/1973 03:45:50');
+$then = new DateTime('1/18/1973 03:45:50');
+$then->modify('+55 days 2 hours 17 minutes 2 seconds');
+
+printf("Birthtime is: %s\nthen is: %s\n", $birthtime->format(DATE_RFC1123), $then->format(DATE_RFC1123));
+
+// @@PLEAC@@_3.5
+// Date intervals are most easily computed using timestamps [i.e. *NIX Epoch
+// Seconds] which, of course, gives the interval result is seconds from which
+// all other interval measures [days, weeks, months, years] may be derived.
+// Refer to previous section for discussion of daylight saving and other related
+// problems
+
+$interval_seconds = $recent - $earlier;
+
+// ----------------------------
+
+// Conventional approach ...
+$bree = strtotime('16 Jun 1981, 4:35:25');
+$nat = strtotime('18 Jan 1973, 3:45:50');
+
+// ... or, with daylight saving adjustment
+$bree = mktime(4, 35, 25, 6, 16, 1981, TRUE);
+$nat = mktime(3, 45, 50, 1, 18, 1973, TRUE);
+
+$difference = $bree - $nat;
+
+// 'dateInterval' custom function computes intervals in several measures given an
+// interval in seconds. Note, 'month' and 'year' measures not provided
+printf("There were %d seconds between Nat and Bree\n", $difference);
+printf("There were %d weeks between Nat and Bree\n", dateInterval('weeks', $difference));
+printf("There were %d days between Nat and Bree\n", dateInterval('days', $difference));
+printf("There were %d hours between Nat and Bree\n", dateInterval('hours', $difference));
+printf("There were %d minutes between Nat and Bree\n", dateInterval('mins', $difference));
+
+// @@PLEAC@@_3.6
+// 'getdate' accepts a timestamp [or implicitly calls 'time'] and returns an array of
+// date components. It returns much the same information as 'strptime' except that
+// the component names are different
+
+$today = getdate();
+
+$weekday = $today['wday'];
+$monthday = $today['mday'];
+$yearday = $today['yday'];
+
+$weeknumber = (int) round($yearday / 7.0);
+
+// Safter method of obtaining week number
+$weeknumber = strftime('%U') + 1;
+
+// ----------------------------
+
+define(SEP, '/');
+
+$day = 16;
+$month = 6;
+$year = 1981;
+
+$timestamp = mktime(0, 0, 0, $month, $day, $year);
+
+$date = getdate($timestamp);
+
+$weekday = $date['wday'];
+$monthday = $date['mday'];
+$yearday = $date['yday'];
+
+$weeknumber = (int) round($yearday / 7.0);
+
+$weeknumber = strftime('%U', $timestamp) + 1;
+
+// Interpolate ...
+$sep = SEP;
+echo "{$month}{$sep}{$day}{$sep}{$year} was a {$date['weekday']} in week {$weeknumber}\n";
+
+// ... or, concatenate
+echo $month . SEP . $day . SEP . $year . ' was a ' . $date['weekday']
+ . ' in week ' . $weeknumber . "\n";
+
+// @@PLEAC@@_3.7
+// 'strtotime' parses a textual date expression by attempting a 'best guess' at
+// the format, and either fails, or generates a timestamp. Timestamp could be fed
+// into any one of the various functions; example:
+$timestamp = strtotime('1998-06-03'); echo strftime('%Y-%m-%d', $timestamp) . "\n";
+
+// 'strptime' parses a textual date expression according to a specified format,
+// and returns an array of date components; components can be easily dumped
+print_r(strptime('1998-06-03', '%Y-%m-%d'));
+
+// ----------------------------
+
+// Parse date string according to format
+$darr = strptime('1998-06-03', '%Y-%m-%d');
+
+if (!empty($darr))
+{
+ // Show date components in 'debug' form
+ print_r($darr);
+
+ // Check whether there was a parse error i.e. one or more components could not
+ // be extracted from the string
+ if (empty($darr['unparsed']))
+ {
+ // Properly parsed date, so validate required components using, 'checkdate'
+ if (checkdate($darr['tm_mon'] + 1, $darr['tm_mday'], $darr['tm_year'] + 1900))
+ echo "Parsed date verified as correct\n";
+ else
+ echo "Parsed date failed verification\n";
+ }
+ else
+ {
+ echo "Date string parse not complete; failed components: {$darr['unparsed']}\n";
+ }
+}
+else
+{
+ echo "Date string could not be parsed\n";
+}
+
+// @@PLEAC@@_3.8
+// 'date' and 'strftime' both print a date string based on:
+// * Format String, describing layout of date components
+// * Timestamp [*NIX Epoch Seconds], either given explicitly, or implictly
+// via a call to 'time' which retrieves current time value
+
+$ts = 1234567890;
+
+date('Y/m/d', $ts);
+date('Y/m/d', mktime($h, $m, $s, $mth, $d, $y, $is_dst));
+
+date('Y/m/d'); // same as: date('Y/m/d', time());
+
+// ------------
+
+$ts = 1234567890;
+
+strftime('%Y/%m/%d', $ts);
+strftime('%Y/%m/%d', mktime($h, $m, $s, $mth, $d, $y, $is_dst));
+
+strftime('%Y/%m/%d'); // same as: strftime('%Y/%m/%d', time());
+
+// ----------------------------
+
+// 'mktime' creates a local time timestamp
+$t = strftime('%a %b %e %H:%M:%S %z %Y', mktime(3, 45, 50, 1, 18, 73, TRUE));
+echo "{$t}\n";
+
+// 'gmmktime' creates a GMT time timestamp
+$t = strftime('%a %b %e %H:%M:%S %z %Y', gmmktime(3, 45, 50, 1, 18, 73));
+echo "{$t}\n";
+
+// ----------------------------
+
+// 'strtotime' parses a textual date expression, and generates a timestamp
+$t = strftime('%A %D', strtotime('18 Jan 1973, 3:45:50'));
+echo "{$t}\n";
+
+// This should generate output identical to previous example
+$t = strftime('%A %D', mktime(3, 45, 50, 1, 18, 73, TRUE));
+echo "{$t}\n";
+
+// @@PLEAC@@_3.9
+// PHP 5 and above can use the built-in, 'microtime'. Crude implementation for ealier versions:
+// function microtime() { $t = gettimeofday(); return (float) ($t['sec'] + $t['usec'] / 1000000.0); }
+
+// ------------
+
+$before = microtime();
+
+$line = fgets(STDIN);
+
+$elapsed = microtime() - $before;
+
+printf("You took %.3f seconds\n", $elapsed);
+
+// ------------
+
+define(NUMBER_OF_TIMES, 100);
+define(SIZE, 500);
+
+for($i = 0; $i < NUMBER_OF_TIMES; $i++)
+{
+ $arr = array();
+ for($j = 0; $j < SIZE; $j++) $arr[] = rand();
+
+ $begin = microtime();
+ sort($arr);
+ $elapsed = microtime() - $begin;
+
+ $total_time += $elapsed;
+}
+
+printf("On average, sorting %d random numbers takes %.5f seconds\n", SIZE, $total_time / (float) NUMBER_OF_TIMES);
+
+// @@PLEAC@@_3.10
+// Low-resolution: sleep time specified in seconds
+sleep(1);
+
+// High-resolution: sleep time specified in microseconds [not reliable under Windows]
+usleep(250000);
+
+// @@PLEAC@@_3.11
+// @@INCOMPLETE@@
+// @@INCOMPLETE@@
+
+// @@PLEAC@@_4.0
+// Nested arrays are supported, and may be easily printed using 'print_r'
+
+$nested = array('this', 'that', 'the', 'other');
+
+$nested = array('this', 'that', array('the', 'other')); print_r($nested);
+
+$tune = array('The', 'Star-Spangled', 'Banner');
+
+// @@PLEAC@@_4.1
+// PHP offers only the 'array' type which is actually an associative array, though
+// may be numerically indexed, to mimic vectors and matrices; there is no separate
+// 'list' type
+
+$a = array('quick', 'brown', 'fox');
+
+// ------------
+
+$a = escapeshellarg('Why are you teasing me?');
+
+// ------------
+
+$lines = <<<END_OF_HERE_DOC
+ The boy stood on the burning deck,
+ it was as hot as glass.
+END_OF_HERE_DOC;
+
+// ------------
+
+$bigarray = array_map('rtrim', file('mydatafile'));
+
+// ------------
+
+$banner = 'The mines of Moria';
+
+$banner = escapeshellarg('The mines of Moria');
+
+// ------------
+
+$name = 'Gandalf';
+
+$banner = "Speak {$name}, and enter!";
+
+$banner = 'Speak ' . escapeshellarg($name) . ' and welcome!';
+
+// ------------
+
+$his_host = 'www.perl.com';
+
+$host_info = `nslookup $his_host`;
+
+$cmd = 'ps ' . posix_getpid(); $perl_info = `$cmd`;
+
+$shell_info = `ps $$`;
+
+// ------------
+
+$banner = array('Costs', 'only', '$4.95');
+
+$banner = array_map('escapeshellarg', split(' ', 'Costs only $4.95'));
+
+// ------------
+
+// AFAIK PHP doesn't support non-quoted strings ala Perl's 'q', 'qq' and 'qw', so arrays
+// created from strings must use quoted strings, and make use of 'split' [or equivalent].
+// A slew of functions exist for performing string quoting, including 'escapeshellarg',
+// 'quotemeta', and 'preg_quote'
+
+$brax = split(' ', '( ) < > { } [ ]');
+
+// Do this to quote each element within '..'
+// $brax = array_map('escapeshellarg', split(' ', '( ) < > { } [ ]'));
+
+$rings = split(' ', 'Nenya Narya Vilya');
+
+$tags = split(' ', 'LI TABLE TR TD A IMG H1 P');
+
+$sample = split(' ', 'The vertical bar | looks and behaves like a pipe.');
+
+// @@PLEAC@@_4.2
+function commify_series($list)
+{
+ $n = str_word_count($list); $series = str_word_count($list, 1);
+
+ if ($n == 0) return NULL;
+ if ($n == 1) return $series[0];
+ if ($n == 2) return $series[0] . ' and ' . $series[1];
+
+ return join(', ', array_slice($series, 0, -1)) . ', and ' . $series[$n - 1];
+}
+
+// ------------
+
+echo commify_series('red') . "\n";
+echo commify_series('red yellow') . "\n";
+echo commify_series('red yellow green') . "\n";
+
+$mylist = 'red yellow green';
+echo 'I have ' . commify_series($mylist) . " marbles.\n";
+
+// ----------------------------
+
+function commify_series($arr)
+{
+ $n = count($arr); $sepchar = ',';
+
+ foreach($arr as $str)
+ {
+ if (strpos($str, ',') === false) continue;
+ $sepchar = ';'; break;
+ }
+
+ if ($n == 0) return NULL;
+ if ($n == 1) return $arr[0];
+ if ($n == 2) return $arr[0] . ' and ' . $arr[1];
+
+ return join("{$sepchar} ", array_slice($arr, 0, -1)) . "{$sepchar} and " . $arr[$n - 1];
+}
+
+// ------------
+
+$lists = array(
+ array('just one thing'),
+ split(' ', 'Mutt Jeff'),
+ split(' ', 'Peter Paul Mary'),
+ array('To our parents', 'Mother Theresa', 'God'),
+ array('pastrami', 'ham and cheese', 'peanut butter and jelly', 'tuna'),
+ array('recycle tired, old phrases', 'ponder big, happy thoughts'),
+ array('recycle tired, old phrases', 'ponder big, happy thoughts', 'sleep and dream peacefully'));
+
+foreach($lists as $arr)
+{
+ echo 'The list is: ' . commify_series($arr) . ".\n";
+}
+
+// @@PLEAC@@_4.3
+// AFAICT you cannot grow / shrink an array to an arbitrary size. However, you can:
+// * Grow an array by appending an element using subscrip notation, or using
+// either 'array_unshift' or 'array_push' to add one or more elements
+
+$arr[] = 'one';
+array_unshift($arr, 'one', 'two', 'three');
+array_push($arr, 'one', 'two', 'three');
+
+// * Shrink an array by using 'unset' to remove one or more specific elements, or
+// either 'array_shift' or 'array_pop' to remove an element from the ends
+
+unset($arr[$idx1], $arr[$idx2], $arr[$idx3]);
+$item = array_shift($arr);
+$item = array_pop($arr);
+
+// ----------------------------
+
+function what_about_the_array()
+{
+ global $people;
+
+ echo 'The array now has ' . count($people) . " elements\n";
+ echo 'The index value of the last element is ' . (count($people) - 1) . "\n";
+ echo 'Element #3 is ' . $people[3] . "\n";
+}
+
+$people = array('Crosby', 'Stills', 'Nash', 'Young');
+what_about_the_array();
+
+array_pop($people);
+what_about_the_array();
+
+// Cannot, AFAICT, resize the array to an arbitrary size
+
+# @@PLEAC@@_4.4
+foreach ($list as $item) {
+ // do something with $item
+}
+
+// Environment listing example
+
+// PHP defines a superglobal $_ENV to provide access to environment
+// variables.
+
+// Beware, array assignment means copying in PHP. You need to use
+// the reference operator to avoid copying. But we want a copy here.
+$env = $_ENV;
+
+// PHP can sort an array by key, so you don't need to get keys,
+// and then sort.
+ksort($env);
+
+foreach ($env as $key => $value) {
+ echo "{$key}={$value}\n";
+}
+
+// Literal translation of Perl example would be:
+$keys = array_keys($_ENV);
+sort($keys);
+foreach ($keys as $key) {
+ echo "{$key}={$_ENV[$key]}\n";
+}
+
+// This assumes that MAX_QUOTA is a named constant.
+foreach ($all_users as $user) {
+ $disk_space = get_usage($user);
+ if ($disk_space > MAX_QUOTA) {
+ complain($user);
+ }
+}
+
+// You can't modify array's elements in-place.
+$array = array(1, 2, 3);
+$newarray = array();
+foreach ($array as $item) {
+ $newarray[] = $item - 1;
+}
+print_r($newarray);
+
+// Before PHP 5, that is. You can precede the reference operator
+// before $item to get reference instead of copy.
+$array = array(1, 2, 3);
+foreach ($array as &$item) {
+ $item--;
+}
+print_r($array);
+
+// TODO: explain the old each() and list() iteration construct.
+// foreach is new in PHP 4, and there are subtle differences.
+
+// @@PLEAC@@_4.5
+// Conventional 'read-only' access
+foreach($array as $item)
+{
+ ; // Can access, but not update, array element referred to by '$item'
+}
+
+// ----
+
+// '&' makes '$item' a reference
+foreach($array as &$item)
+{
+ ; // Update array element referred to by '$item'
+}
+
+// ------------
+
+$arraylen = count($array);
+
+for($i = 0; $i < $arraylen; $i++)
+{
+ ; // '$array' is updateable via subscript notation
+}
+
+// ----------------------------
+
+$fruits = array('Apple', 'Raspberry');
+
+foreach($fruits as &$fruit)
+{
+ echo "{$fruit} tastes good in a pie.\n";
+}
+
+$fruitlen = count($fruits);
+
+for($i = 0; $i < $fruitlen; $i++)
+{
+ echo "{$fruits[$i]} tastes good in a pie.\n";
+}
+
+// ----------------------------
+
+$rogue_cats = array('Blackie', 'Goldie', 'Silkie');
+
+// Take care to assign reference to '$rogue_cats' array via '=&'
+$namelist['felines'] =& $rogue_cats;
+
+// Take care to make '$cat' a reference via '&$' to allow updating
+foreach($namelist['felines'] as &$cat)
+{
+ $cat .= ' [meow]';
+}
+
+// Via array reference
+foreach($namelist['felines'] as $cat)
+{
+ echo "{$cat} purrs hypnotically.\n";
+}
+
+echo "---\n";
+
+// Original array
+foreach($rogue_cats as $cat)
+{
+ echo "{$cat} purrs hypnotically.\n";
+}
+
+// @@PLEAC@@_4.6
+// PHP offers the 'array_unique' function to perform this task. It works with both keyed,
+// and numerically-indexed arrays; keys / indexes are preserved; use of 'array_values'
+// is recommended to reindex numerically-indexed arrays since there will likely be missing
+// indexes
+
+// Remove duplicate values
+$unique = array_unique($array);
+
+// Remove duplicates, and reindex [for numerically-indexed arrays only]
+$unique = array_values(array_unique($array));
+
+// or use:
+$unique = array_keys(array_flip($array));
+
+// ----------------------------
+
+// Selected Perl 'seen' examples
+foreach($list as $item)
+{
+ if (!isset($seen[$item]))
+ {
+ $seen[$item] = TRUE;
+ $unique[] = $item;
+ }
+}
+
+// ------------
+
+foreach($list as $item)
+{
+ $seen[$item] || (++$seen[$item] && ($unique[] = $item));
+}
+
+// ------------
+
+function some_func($item)
+{
+ ; // Do something with '$item'
+}
+
+foreach($list as $item)
+{
+ $seen[$item] || (++$seen[$item] && some_func($item));
+}
+
+// ----------------------------
+
+foreach(array_slice(preg_split('/\n/', `who`), 0, -1) as $user_entry)
+{
+ $user = preg_split('/\s/', $user_entry);
+ $ucnt[$user[0]]++;
+}
+
+ksort($ucnt);
+
+echo "users logged in:\n";
+
+foreach($ucnt as $user => $cnt)
+{
+ echo "\t{$user} => {$cnt}\n";
+}
+
+// @@PLEAC@@_4.7
+// PHP offers the 'array_diff' and 'array_diff_assoc' functions to perform this task. Same
+// points as made about 'array_unique' apply here also
+
+$a = array('c', 'a', 'b', 'd');
+$b = array('c', 'a', 'b', 'e');
+
+$diff = array_diff($a, $b); // $diff -> [3] 'd'
+$diff = array_diff($b, $a); // $diff -> [3] 'e'
+
+// Numerically-indexed array, reindexed
+$diff = array_values(array_diff($a, $b)); // $diff -> [0] 'd'
+$diff = array_values(array_diff($b, $a)); // $diff -> [0] 'e'
+
+// ----------------------------
+
+// 1st Perl 'seen' example only
+
+$a = array('k1' => 11, 'k2' => 12, 'k4' => 14);
+$b = array('k1' => 11, 'k2' => 12, 'k3' => 13);
+
+foreach($b as $item => $value) { $seen[$item] = 1; }
+
+// Stores key only e.g. $aonly[0] contains 'k4', same as Perl example
+foreach($a as $item => $value) { if (!$seen[$item]) $aonly[] = $item; }
+
+// Stores key and value e.g. $aonly['k4'] contains 14, same entry as in $a
+foreach($a as $item => $value) { if (!$seen[$item]) $aonly[$item] = $value; }
+
+// ----------------------------
+
+// Conventional way: $hash = array('key1' => 1, 'key2' => 2);
+
+$hash['key1'] = 1;
+$hash['key2'] = 2;
+
+$hash = array_combine(array('key1', 'key2'), array(1, 2));
+
+// ------------
+
+$seen = array_slice($b, 0);
+
+$seen = array_combine(array_keys($b), array_fill(0, count($b), 1));
+
+// @@PLEAC@@_4.8
+// PHP offers a number of array-based 'set operation' functions:
+// * union: array_unique(array_merge(...))
+// * intersection: array_intersect and family
+// * difference: array_diff and family
+// which may be used for this type of task. Also, if returned arrays need to be
+// reindexed, 'array_slice($array, 0)', or 'array_values($array)' are useful
+
+$a = array(1, 3, 5, 6, 7, 8);
+$b = array(2, 3, 5, 7, 9);
+
+$union = array_values(array_unique(array_merge($a, $b))); // 1, 2, 3, 5, 6, 7, 8, 9
+$isect = array_values(array_intersect($a, $b)); // 3, 5, 7
+$diff = array_values(array_diff($a, $b)); // 1, 8
+
+// @@PLEAC@@_4.9
+// PHP offers the 'array_merge' function to perform this task. Duplicate values are retained,
+// but if arrays are numerically-indexed, resulting array is reindexed
+
+$arr1 = array('c', 'a', 'b', 'd');
+$arr2 = array('c', 'a', 'b', 'e');
+
+$new = array_merge($arr1, $arr2); // $new -> 'c', 'a', 'b', 'd', 'c', 'a', 'b', 'd'
+
+// ----------------------------
+
+$members = array('Time', 'Flies');
+$initiates = array('An', 'Arrow');
+
+$members = array_merge($members, $initiates);
+
+// ------------
+
+$members = array('Time', 'Flies');
+$initiates = array('An', 'Arrow');
+
+// 'array_splice' is the PHP equivalent to Perl's 'splice'
+array_splice($members, 2, 0, array_merge(array('Like'), $initiates));
+echo join(' ', $members) . "\n";
+
+array_splice($members, 0, 1, array('Fruit'));
+array_splice($members, -2, 2, array('A', 'Banana'));
+echo join(' ', $members) . "\n";
+
+// @@PLEAC@@_4.10
+$reversed = array_reverse($array);
+
+// ----------------------------
+
+foreach(array_reverse($array) as $item)
+{
+ ; // ... do something with '$item' ...
+}
+
+// ------------
+
+for($i = count($array) - 1; $i >= 0; $i--)
+{
+ ; // ... do something with '$array[$i]' ...
+}
+
+// ----------------------------
+
+sort($array);
+$array = array_reverse($array);
+
+// ------------
+
+rsort($array);
+
+// @@PLEAC@@_4.11
+// Array elements can be deleted using 'unset'; removing several elements would require applying
+// 'unset' several times, probably in a loop. However, they would most likely also need to be
+// reindexed, so a better approach would be to use 'array_slice' which avoids explicit looping.
+// Where elements need to be removed, and those elements also returned, it is probably best to
+// combine both operations in a function. This is the approach taken here in implementing both
+// 'shiftN' and 'popN', and it is these functions that are used in the examples
+
+function popN(&$arr, $n)
+{
+ $ret = array_slice($arr, -($n), $n);
+ $arr = array_slice($arr, 0, count($arr) - $n);
+ return $ret;
+}
+
+function shiftN(&$arr, $n)
+{
+ $ret = array_slice($arr, 0, $n);
+ $arr = array_slice($arr, $n);
+ return $ret;
+}
+
+// ------------
+
+// Remove $n elements from the front of $array; return them in $fron
+$front = shiftN($array, $n);
+
+// Remove $n elements from the end of $array; return them in $end
+$end = popN($array, $n);
+
+// ------------
+
+$friends = array('Peter', 'Paul', 'Mary', 'Jim', 'Tim');
+
+list($this_, $that) = shiftN($friends, 2);
+
+echo "{$this_} {$that}\n";
+
+// ------------
+
+$beverages = array('Dew', 'Jolt', 'Cola', 'Sprite', 'Fresca');
+
+$pair = popN($beverages, 2);
+
+echo join(' ', $pair) . "\n";
+
+// @@PLEAC@@_4.12
+// This section illustrates various 'find first' techniques. The Perl examples all use an
+// explicit loop and condition testing [also repeated here]. This is the simplest, and
+// [potentially] most efficient approach because the search can be terminated as soon as a
+// match is found. However, it is worth mentioning a few alternatives:
+// * 'array_search' performs a 'find first' using the element value rather than a condition
+// check, so isn't really applicable here
+// * 'array_filter', whilst using a condition check, actually performs a 'find all', though
+// all but the first returned element can be discarded. This approach is actually less error
+// prone than using a loop, but the disadvantage is that each element is visited: there is no
+// means of terminating the search once a match has been found. It would be nice if this
+// function were to have a third parameter, a Boolean flag indicating whether to traverse
+// the whole array, or quit after first match [next version, maybe :) ?]
+
+$found = FALSE;
+
+foreach($array as $item)
+{
+ // Not found - skip to next item
+ if (!$criterion) continue;
+
+ // Found - save and leave
+ $match = $item;
+ $found = TRUE;
+ break;
+}
+
+if ($found)
+{
+ ; // do something with $match
+}
+else
+{
+ ; // not found
+}
+
+// ------------
+
+function predicate($element)
+{
+ if (criterion) return TRUE;
+ return FALSE;
+}
+
+$match = array_slice(array_filter($array, 'predicate'), 0, 1);
+
+if ($match)
+{
+ ; // do something with $match[0]
+}
+else
+{
+ ; // $match is empty - not found
+}
+
+// ----------------------------
+
+class Employee
+{
+ public $name, $age, $ssn, $salary;
+
+ public function __construct($name, $age, $ssn, $salary, $category)
+ {
+ $this->name = $name;
+ $this->age = $age;
+ $this->ssn = $ssn;
+ $this->salary = $salary;
+ $this->category = $category;
+ }
+}
+
+// ------------
+
+$employees = array(
+ new Employee('sdf', 27, 12345, 47000, 'Engineer'),
+ new Employee('ajb', 32, 12376, 51000, 'Programmer'),
+ new Employee('dgh', 31, 12355, 45000, 'Engineer'));
+
+// ------------
+
+function array_update($arr, $lambda, $updarr)
+{
+ foreach($arr as $key) $lambda($updarr, $key);
+ return $updarr;
+}
+
+function highest_salaried_engineer(&$arr, $employee)
+{
+ static $highest_salary = 0;
+
+ if ($employee->category == 'Engineer')
+ {
+ if ($employee->salary > $highest_salary)
+ {
+ $highest_salary = $employee->salary;
+ $arr[0] = $employee;
+ }
+ }
+}
+
+// ------------
+
+// 'array_update' custom function is modelled on 'array_reduce' except that it allows the
+// return of an array, contents and length of which are entirely dependant on what the
+// callback function does. Here, it is logically working in a 'find first' capacity
+$highest_salaried_engineer = array_update($employees, 'highest_salaried_engineer', array());
+
+echo 'Highest paid engineer is: ' . $highest_salaried_engineer[0]->name . "\n";
+
+// @@PLEAC@@_4.13
+// PHP implements 'grep' functionality [as embodied in the current section] in the 'array_filter'
+// function
+
+function predicate($element)
+{
+ if (criterion) return TRUE;
+ return FALSE;
+}
+
+$matching = array_filter($list, 'predicate');
+
+// ------------
+
+$bigs = array_filter($nums, create_function('$n', 'return $n > 1000000;'));
+
+// ------------
+
+function is_pig($user)
+{
+ $user_details = preg_split('/(\s)+/', $user);
+ // Assuming field 5 is the resource being compared
+ return $user_details[5] > 1e7;
+}
+
+$pigs = array_filter(array_slice(preg_split('/\n/', `who -u`), 0, -1), 'is_pig');
+
+// ------------
+
+$matching = array_filter(array_slice(preg_split('/\n/', `who`), 0, -1),
+ create_function('$user', 'return preg_match(\'/^gnat /\', $user);'));
+
+// ------------
+
+class Employee
+{
+ public $name, $age, $ssn, $salary;
+
+ public function __construct($name, $age, $ssn, $salary, $category)
+ {
+ $this->name = $name;
+ $this->age = $age;
+ $this->ssn = $ssn;
+ $this->salary = $salary;
+ $this->category = $category;
+ }
+}
+
+// ------------
+
+$employees = array(
+ new Employee('sdf', 27, 12345, 47000, 'Engineer'),
+ new Employee('ajb', 32, 12376, 51000, 'Programmer'),
+ new Employee('dgh', 31, 12355, 45000, 'Engineer'));
+
+// ------------
+
+$engineers = array_filter($employees,
+ create_function('$employee', 'return $employee->category == "Engineer";'));
+
+// @@PLEAC@@_4.14
+// PHP offers a rich set of sorting functions. Key features:
+// * Inplace sorts; the original array, not a a copy, is sorted
+// * Separate functions exist for sorting [both ascending and descending order]:
+// - By value, assign new keys / indices [sort, rsort]
+// - By key [ksort, krsort] (for non-numerically indexed arrays)
+// - By value [asort, arsort]
+// - As above, but using a user-defined comparator [i.e. callback function]
+// [usort, uasort, uksort]
+// - Natural order sort [natsort]
+// * Significantly, if sorting digit-only elements, whether strings or numbers,
+// 'natural order' [i.e. 1 before 10 before 100 (ascending)] is retained. If
+// the elements are alphanumeric e.g. 'z1', 'z10' then 'natsort' should be
+// used [note: beware of 'natsort' with negative numbers; prefer 'sort' or 'asort']
+
+$unsorted = array(7, 12, -13, 2, 100, 5, 1, -2, 23, 3, 6, 4);
+
+sort($unsorted); // -13, -2, 1, 2, 3, 4, 5, 6, 7, 12, 23, 100
+rsort($unsorted); // 100, 23, 12, 7, 6, 5, 4, 3, 2, 1, -2, -13
+
+asort($unsorted); // -13, -2, 1, 2, 3, 4, 5, 6, 7, 12, 23, 100
+arsort($unsorted); // 100, 23, 12, 7, 6, 5, 4, 3, 2, 1, -2, -13
+
+natsort($unsorted); // -2, -13, 1, 2, 3, 4, 5, 6, 7, 12, 23, 100
+
+// ------------
+
+function ascend($left, $right) { return $left > $right; }
+function descend($left, $right) { return $left < $right; }
+
+// ------------
+
+usort($unsorted, 'ascend'); // -13, -2, 1, 2, 3, 4, 5, 6, 7, 12, 23, 100
+usort($unsorted, 'descend'); // 100, 23, 12, 7, 6, 5, 4, 3, 2, 1, -2, -13
+
+uasort($unsorted, 'ascend'); // -13, -2, 1, 2, 3, 4, 5, 6, 7, 12, 23, 100
+uasort($unsorted, 'descend'); // 100, 23, 12, 7, 6, 5, 4, 3, 2, 1, -2, -13
+
+// ----------------------------
+
+function kill_process($pid)
+{
+ // Is 'killable' ?
+ if (!posix_kill($pid, 0)) return;
+
+ // Ok, so kill in two stages
+ posix_kill($pid, 15); // SIGTERM
+ sleep(1);
+ posix_kill($pid, 9); // SIGKILL
+}
+
+function pid($pentry)
+{
+ $p = preg_split('/\s/', trim($pentry));
+ return $p[0];
+}
+
+$processes = array_map('pid', array_slice(preg_split('/\n/', `ps ax`), 1, -1));
+sort($processes);
+
+echo join(' ,', $processes) . "\n";
+
+echo 'Enter a pid to kill: ';
+if (($pid = trim(fgets(STDIN))))
+ kill_process($pid);
+
+// @@PLEAC@@_4.15
+// Tasks in this section would typically use the PHP 'usort' family of functions
+// which are used with a comparator function so as to perform custom comparisions.
+// A significant difference from the Perl examples is that these functions are
+// inplace sorters, so it is the original array that is modified. Where this must
+// be prevented a copy of the array can be made and sorted
+
+function comparator($left, $right)
+{
+ ; // Compare '$left' with '$right' returning result
+}
+
+// ------------
+
+$ordered = array_slice($unordered);
+usort($ordered, 'comparator');
+
+// ----------------------------
+
+// The Perl example looks like it is creating a hash using computed values as the key,
+// array values as the value, sorting on the computed key, then extracting the sorted
+// values and placing them back into an array
+
+function compute($value)
+{
+ ; // Return computed value utilising '$value'
+}
+
+// ------------
+
+// Original numerically-indexed array [sample data used]
+$unordered = array(5, 3, 7, 1, 4, 2, 6);
+
+// Create hash using 'compute' function to generate the keys. This example assumes that
+// each value in the '$unordered' array is used in generating the corresponding '$key'
+foreach($unordered as $value)
+{
+ $precomputed[compute($value)] = $value;
+}
+
+// Copy the hash, and sort it by key
+$ordered_precomputed = array_slice($precomputed, 0); ksort($ordered_precomputed);
+
+// Extract the values of the hash in current order placing them in a new numerically-indexed
+// array
+$ordered = array_values($ordered_precomputed);
+
+// ----------------------------
+
+// As above, except uses 'array_update' and 'accum' to help create hash
+
+function array_update($arr, $lambda, $updarr)
+{
+ foreach($arr as $key) $lambda($updarr, $key);
+ return $updarr;
+}
+
+function accum(&$arr, $value)
+{
+ $arr[compute($value)] = $value;
+}
+
+// ------------
+
+function compute($value)
+{
+ ; // Return computed value utilising '$value'
+}
+
+// ------------
+
+// Original numerically-indexed array [sample data used]
+$unordered = array(5, 3, 7, 1, 4, 2, 6);
+
+// Create hash
+$precomputed = array_update($unordered, 'accum', array());
+
+// Copy the hash, and sort it by key
+$ordered_precomputed = array_slice($precomputed, 0); ksort($ordered_precomputed);
+
+// Extract the values of the hash in current order placing them in a new numerically-indexed
+// array
+$ordered = array_values($ordered_precomputed);
+
+// ----------------------------
+
+class Employee
+{
+ public $name, $age, $ssn, $salary;
+
+ public function __construct($name, $age, $ssn, $salary)
+ {
+ $this->name = $name;
+ $this->age = $age;
+ $this->ssn = $ssn;
+ $this->salary = $salary;
+ }
+}
+
+// ------------
+
+$employees = array(
+ new Employee('sdf', 27, 12345, 47000),
+ new Employee('ajb', 32, 12376, 51000),
+ new Employee('dgh', 31, 12355, 45000));
+
+// ------------
+
+$ordered = array_slice($employees, 0);
+usort($ordered, create_function('$left, $right', 'return $left->name > $right->name;'));
+
+// ------------
+
+$sorted_employees = array_slice($employees, 0);
+usort($sorted_employees, create_function('$left, $right', 'return $left->name > $right->name;'));
+
+$bonus = array(12376 => 5000, 12345 => 6000, 12355 => 0);
+
+foreach($sorted_employees as $employee)
+{
+ echo "{$employee->name} earns \${$employee->salary}\n";
+}
+
+foreach($sorted_employees as $employee)
+{
+ if (($amount = $bonus[$employee->ssn]))
+ echo "{$employee->name} got a bonus of: \${$amount}\n";
+}
+
+// ------------
+
+$sorted = array_slice($employees, 0);
+usort($sorted, create_function('$left, $right', 'return $left->name > $right->name || $left->age != $right->age;'));
+
+// ----------------------------
+
+// PHP offers a swag of POSIX functions for obtaining user information [i.e. they all read
+// the '/etc/passwd' file for the relevant infroamtion], and it is these that should rightly
+// be used for this purpose. However, since the intent of this section is to illustrate array
+// manipulation, these functions won't be used. Instead a custom function mimicing Perl's
+// 'getpwent' function will be implemented so the code presented here can more faithfully match
+// the Perl code
+
+function get_pw_entries()
+{
+ function normal_users_only($e)
+ {
+ $entry = split(':', $e); return $entry[2] > 100 && $entry[2] < 32768;
+ }
+
+ foreach(array_filter(file('/etc/passwd'), 'normal_users_only') as $entry)
+ $users[] = split(':', trim($entry));
+
+ return $users;
+}
+
+// ------------
+
+$users = get_pw_entries();
+
+usort($users, create_function('$left, $right', 'return $left[0] > $right[0];'));
+foreach($users as $user) echo "{$user[0]}\n";
+
+// ----------------------------
+
+$names = array('sdf', 'ajb', 'dgh');
+
+$sorted = array_slice($names, 0);
+usort($sorted, create_function('$left, $right', 'return substr($left, 1, 1) > substr($right, 1, 1);'));
+
+// ------------
+
+$strings = array('bbb', 'aa', 'c');
+
+$sorted = array_slice($strings, 0);
+usort($sorted, create_function('$left, $right', 'return strlen($left) > strlen($right);'));
+
+// ----------------------------
+
+function array_update($arr, $lambda, $updarr)
+{
+ foreach($arr as $key) $lambda($updarr, $key);
+ return $updarr;
+}
+
+function accum(&$arr, $value)
+{
+ $arr[strlen($value)] = $value;
+}
+
+// ----
+
+$strings = array('bbb', 'aa', 'c');
+
+$temp = array_update($strings, 'accum', array());
+ksort($temp);
+$sorted = array_values($temp);
+
+// ----------------------------
+
+function array_update($arr, $lambda, $updarr)
+{
+ foreach($arr as $key) $lambda($updarr, $key);
+ return $updarr;
+}
+
+function accum(&$arr, $value)
+{
+ if (preg_match('/(\d+)/', $value, $matches))
+ $arr[$matches[1]] = $value;
+}
+
+// ----
+
+$fields = array('b1b2b', 'a4a', 'c9', 'ddd', 'a');
+
+$temp = array_update($fields, 'accum', array());
+ksort($temp);
+$sorted_fields = array_values($temp);
+
+// @@PLEAC@@_4.16
+array_unshift($a1, array_pop($a1)); // last -> first
+array_push($a1, array_shift($a1)); // first -> last
+
+// ----------------------------
+
+function grab_and_rotate(&$arr)
+{
+ $item = $arr[0];
+ array_push($arr, array_shift($arr));
+ return $item;
+}
+
+// ------------
+
+$processes = array(1, 2, 3, 4, 5);
+
+while (TRUE)
+{
+ $process = grab_and_rotate($processes);
+ echo "Handling process {$process}\n";
+ sleep(1);
+}
+
+// @@PLEAC@@_4.17
+// PHP offers the 'shuffle' function to perform this task
+
+$arr = array(1, 2, 3, 4, 5, 6, 7, 8, 9);
+
+shuffle($arr);
+
+echo join(' ', $arr) . "\n";
+
+// ----------------------------
+
+// Perl example equivalents
+function fisher_yates_shuffle(&$a)
+{
+ $size = count($a) - 1;
+
+ for($i = $size; $i >= 0; $i--)
+ {
+ if (($j = rand(0, $i)) != $i)
+ list($a[$i], $a[$j]) = array($a[$j], $a[$i]);
+ }
+}
+
+function naive_shuffle(&$a)
+{
+ $size = count($a);
+
+ for($i = 0; $i < $size; $i++)
+ {
+ $j = rand(0, $size - 1);
+ list($a[$i], $a[$j]) = array($a[$j], $a[$i]);
+ }
+}
+
+// ------------
+
+$arr = array(1, 2, 3, 4, 5, 6, 7, 8, 9);
+
+fisher_yates_shuffle($arr);
+echo join(' ', $arr) . "\n";
+
+naive_shuffle($arr);
+echo join(' ', $arr) . "\n";
+
+// @@PLEAC@@_4.18
+// @@INCOMPLETE@@
+// @@INCOMPLETE@@
+
+// @@PLEAC@@_4.19
+// @@INCOMPLETE@@
+// @@INCOMPLETE@@
+
+// @@PLEAC@@_5.0
+// PHP uses the term 'array' to refer to associative arrays - referred to in Perl
+// as 'hashes' - and for the sake of avoiding confusion, the Perl terminology will
+// be used. As a matter of interest, PHP does not sport a vector, matrix, or list
+// type: the 'array' [Perl 'hash'] serves all these roles
+
+$age = array('Nat' => 24, 'Jules' => 25, 'Josh' => 17);
+
+$age['Nat'] = 24;
+$age['Jules'] = 25;
+$age['Josh'] = 17;
+
+$age = array_combine(array('Nat', 'Jules', 'Josh'), array(24, 25, 17));
+
+// ------------
+
+$food_colour = array('Apple' => 'red', 'Banana' => 'yellow',
+ 'Lemon' => 'yellow', 'Carrot' => 'orange');
+
+$food_colour['Apple'] = 'red'; $food_colour['Banana'] = 'yellow';
+$food_colour['Lemon'] = 'yellow'; $food_colour['Carrot'] = 'orange';
+
+$food_colour = array_combine(array('Apple', 'Banana', 'Lemon', 'Carrot'),
+ array('red', 'yellow', 'yellow', 'orange'));
+
+// @@PLEAC@@_5.1
+$hash[$key] = $value;
+
+// ------------
+
+$food_colour = array('Apple' => 'red', 'Banana' => 'yellow',
+ 'Lemon' => 'yellow', 'Carrot' => 'orange');
+
+$food_colour['Raspberry'] = 'pink';
+
+echo "Known foods:\n";
+foreach($food_colour as $food => $colour) echo "{$food}\n";
+
+// @@PLEAC@@_5.2
+// Returns TRUE on all existing entries with non-NULL values
+if (isset($hash[$key]))
+ ; // entry exists
+else
+ ; // no such entry
+
+// ------------
+
+// Returns TRUE on all existing entries regardless of attached value
+if (array_key_exists($key, $hash))
+ ; // entry exists
+else
+ ; // no such entry
+
+// ----------------------------
+
+$food_colour = array('Apple' => 'red', 'Banana' => 'yellow',
+ 'Lemon' => 'yellow', 'Carrot' => 'orange');
+
+foreach(array('Banana', 'Martini') as $name)
+{
+ if (isset($food_colour[$name]))
+ echo "{$name} is a food.\n";
+ else
+ echo "{$name} is a drink.\n";
+}
+
+// ----------------------------
+
+$age = array('Toddler' => 3, 'Unborn' => 0, 'Phantasm' => NULL);
+
+foreach(array('Toddler', 'Unborn', 'Phantasm', 'Relic') as $thing)
+{
+ echo "{$thing}:";
+ if (array_key_exists($thing, $age)) echo ' exists';
+ if (isset($age[$thing])) echo ' non-NULL';
+ if ($age[$thing]) echo ' TRUE';
+ echo "\n";
+}
+
+// @@PLEAC@@_5.3
+// Remove one, or more, hash entries
+unset($hash[$key]);
+
+unset($hash[$key1], $hash[$key2], $hash[$key3]);
+
+// Remove entire hash
+unset($hash);
+
+// ----------------------------
+
+function print_foods()
+{
+ // Perl example uses a global variable
+ global $food_colour;
+
+ $foods = array_keys($food_colour);
+
+ echo 'Foods:';
+ foreach($foods as $food) echo " {$food}";
+
+ echo "\nValues:\n";
+ foreach($foods as $food)
+ {
+ $colour = $food_colour[$food];
+
+ if (isset($colour))
+ echo " {$colour}\n";
+ else
+ echo " nullified or removed\n";
+ }
+}
+
+// ------------
+
+$food_colour = array('Apple' => 'red', 'Banana' => 'yellow',
+ 'Lemon' => 'yellow', 'Carrot' => 'orange');
+
+echo "Initially:\n"; print_foods();
+
+// Nullify an entry
+$food_colour['Banana'] = NULL;
+echo "\nWith 'Banana' nullified\n";
+print_foods();
+
+// Remove an entry
+unset($food_colour['Banana']);
+echo "\nWith 'Banana' removed\n";
+print_foods();
+
+// Destroy the hash
+unset($food_colour);
+
+// @@PLEAC@@_5.4
+// Access keys and values
+foreach($hash as $key => $value)
+{
+ ; // ...
+}
+
+// Access keys only
+foreach(array_keys($hash) as $key)
+{
+ ; // ...
+}
+
+// Access values only
+foreach($hash as $value)
+{
+ ; // ...
+}
+
+// ----------------------------
+
+$food_colour = array('Apple' => 'red', 'Banana' => 'yellow',
+ 'Lemon' => 'yellow', 'Carrot' => 'orange');
+
+foreach($food_colour as $food => $colour)
+{
+ echo "{$food} is {$colour}\n";
+}
+
+foreach(array_keys($food_colour) as $food)
+{
+ echo "{$food} is {$food_colour[$food]}\n";
+}
+
+// ----------------------------
+
+// 'countfrom' - count number of messages from each sender
+
+$line = fgets(STDIN);
+
+while (!feof(STDIN))
+{
+ if (preg_match('/^From: (.*)/', $line, $matches))
+ {
+ if (isset($from[$matches[1]]))
+ $from[$matches[1]] += 1;
+ else
+ $from[$matches[1]] = 1;
+ }
+
+ $line = fgets(STDIN);
+}
+
+if (isset($from))
+{
+ echo "Senders:\n";
+ foreach($from as $sender => $count) echo "{$sender} : {$count}\n";
+}
+else
+{
+ echo "No valid data entered\n";
+}
+
+// @@PLEAC@@_5.5
+// PHP offers, 'print_r', which prints hash contents in 'debug' form; it also
+// works recursively, printing any contained arrays in similar form
+// Array
+// (
+// [key1] => value1
+// [key2] => value2
+// ...
+// )
+
+print_r($hash);
+
+// ------------
+
+// Based on Perl example; non-recursive, so contained arrays not printed correctly
+foreach($hash as $key => $value)
+{
+ echo "{$key} => $value\n";
+}
+
+// ----------------------------
+
+// Sorted by keys
+
+// 1. Sort the original hash
+ksort($hash);
+
+// 2. Extract keys, sort, traverse original in key order
+$keys = array_keys($hash); sort($keys);
+
+foreach($keys as $key)
+{
+ echo "{$key} => {$hash[$key]}\n";
+}
+
+// Sorted by values
+
+// 1. Sort the original hash
+asort($hash);
+
+// 2. Extract values, sort, traverse original in value order [warning: finds
+// only first matching key in the case where duplicate values exist]
+$values = array_values($hash); sort($values);
+
+foreach($values as $value)
+{
+ echo $value . ' <= ' . array_search($value, $hash) . "\n";
+}
+
+// @@PLEAC@@_5.6
+// Unless sorted, hash elements remain in the order of insertion. If care is taken to
+// always add a new element to the end of the hash, then element order is the order
+// of insertion. The following function, 'array_push_associative' [modified from original
+// found at 'array_push' section of PHP documentation], does just that
+function array_push_associative(&$arr)
+{
+ foreach (func_get_args() as $arg)
+ {
+ if (is_array($arg))
+ foreach ($arg as $key => $value) { $arr[$key] = $value; $ret++; }
+ else
+ $arr[$arg] = '';
+ }
+
+ return $ret;
+}
+
+// ------------
+
+$food_colour = array();
+
+// Individual calls, or ...
+array_push_associative($food_colour, array('Banana' => 'Yellow'));
+array_push_associative($food_colour, array('Apple' => 'Green'));
+array_push_associative($food_colour, array('Lemon' => 'Yellow'));
+
+// ... one call, one array; physical order retained
+// array_push_associative($food_colour, array('Banana' => 'Yellow', 'Apple' => 'Green', 'Lemon' => 'Yellow'));
+
+print_r($food_colour);
+
+echo "\nIn insertion order:\n";
+foreach($food_colour as $food => $colour) echo " {$food} => {$colour}\n";
+
+$foods = array_keys($food_colour);
+
+echo "\nStill in insertion order:\n";
+foreach($foods as $food) echo " {$food} => {$food_colour[$food]}\n";
+
+// @@PLEAC@@_5.7
+foreach(array_slice(preg_split('/\n/', `who`), 0, -1) as $entry)
+{
+ list($user, $tty) = preg_split('/\s/', $entry);
+ $ttys[$user][] = $tty;
+
+ // Could instead do this:
+ // $user = array_slice(preg_split('/\s/', $entry), 0, 2);
+ // $ttys[$user[0]][] = $user[1];
+}
+
+ksort($ttys);
+
+// ------------
+
+foreach($ttys as $user => $all_ttys)
+{
+ echo "{$user}: " . join(' ', $all_ttys) . "\n";
+}
+
+// ------------
+
+foreach($ttys as $user => $all_ttys)
+{
+ echo "{$user}: " . join(' ', $all_ttys) . "\n";
+
+ foreach($all_ttys as $tty)
+ {
+ $stat = stat('/dev/$tty');
+ $pwent = posix_getpwuid($stat['uid']);
+ $user = isset($pwent['name']) ? $pwent['name'] : 'Not available';
+ echo "{$tty} owned by: {$user}\n";
+ }
+}
+
+// @@PLEAC@@_5.8
+// PHP offers the 'array_flip' function to perform the task of exchanging the keys / values
+// of a hash i.e. invert or 'flip' a hash
+
+$reverse = array_flip($hash);
+
+// ----------------------------
+
+$surname = array('Babe' => 'Ruth', 'Mickey' => 'Mantle');
+$first_name = array_flip($surname);
+
+echo "{$first_name['Mantle']}\n";
+
+// ----------------------------
+
+$argc == 2 || die("usage: {$argv[0]} food|colour\n");
+
+$given = $argv[1];
+
+$colour = array('Apple' => 'red', 'Banana' => 'yellow',
+ 'Lemon' => 'yellow', 'Carrot' => 'orange');
+
+$food = array_flip($colour);
+
+if (isset($colour[$given]))
+ echo "{$given} is a food with colour: {$colour[$given]}\n";
+
+if (isset($food[$given]))
+ echo "{$food[$given]} is a food with colour: {$given}\n";
+
+// ----------------------------
+
+$food_colour = array('Apple' => 'red', 'Banana' => 'yellow',
+ 'Lemon' => 'yellow', 'Carrot' => 'orange');
+
+foreach($food_colour as $food => $colour)
+{
+ $foods_with_colour[$colour][] = $food;
+}
+
+$colour = 'yellow';
+echo "foods with colour {$colour} were: " . join(' ', $foods_with_colour[$colour]) . "\n";
+
+// @@PLEAC@@_5.9
+// PHP implements a swag of sorting functions, most designed to work with numerically-indexed
+// arrays. For sorting hashes, the 'key' sorting functions are required:
+// * 'ksort', 'krsort', 'uksort'
+
+// Ascending order
+ksort($hash);
+
+// Descending order [i.e. reverse sort]
+krsort($hash);
+
+// Comparator-based sort
+
+function comparator($left, $right)
+{
+ // Compare left key with right key
+ return $left > $right;
+}
+
+uksort($hash, 'comparator');
+
+// ----------------------------
+
+$food_colour = array('Apple' => 'red', 'Banana' => 'yellow',
+ 'Lemon' => 'yellow', 'Carrot' => 'orange');
+
+// ------------
+
+ksort($food_colour);
+
+foreach($food_colour as $food => $colour)
+{
+ echo "{$food} is {$colour}\n";
+}
+
+// ------------
+
+uksort($food_colour, create_function('$left, $right', 'return $left > $right;'));
+
+foreach($food_colour as $food => $colour)
+{
+ echo "{$food} is {$colour}\n";
+}
+
+// @@PLEAC@@_5.10
+// PHP offers the 'array_merge' function for this task [a related function, 'array_combine',
+// may be used to create a hash from an array of keys, and one of values, respectively]
+
+// Merge two, or more, arrays
+$merged = array_merge($a, $b, $c);
+
+// Create a hash from array of keys, and of values, respectively
+$hash = array_combine($keys, $values);
+
+// ------------
+
+// Can always merge arrays manually
+foreach(array($h1, $h2, $h3) as $hash)
+{
+ foreach($hash as $key => $value)
+ {
+ // If same-key values differ, only latest retained
+ $merged[$key] = $value;
+
+ // Do this to append values for that key
+ // $merged[$key][] = $value;
+ }
+}
+
+// ----------------------------
+
+$food_colour = array('Apple' => 'red', 'Banana' => 'yellow',
+ 'Lemon' => 'yellow', 'Carrot' => 'orange');
+
+$drink_colour = array('Galliano' => 'yellow', 'Mai Tai' => 'blue');
+
+// ------------
+
+$ingested_colour = array_merge($food_colour, $drink_colour);
+
+// ------------
+
+$substance_colour = array();
+
+foreach(array($food_colour, $drink_colour) as $hash)
+{
+ foreach($hash as $substance => $colour)
+ {
+ if (array_key_exists($substance, $substance_colour))
+ {
+ echo "Warning {$substance_colour[$substance]} seen twice. Using first definition.\n";
+ continue;
+ }
+ $substance_colour[$substance] = $colour;
+ }
+}
+
+// @@PLEAC@@_5.11
+// PHP offers a number of array-based 'set operation' functions:
+// * union: array_merge
+// * intersection: array_intersect and family
+// * difference: array_diff and family
+// which may be used for this type of task
+
+// Keys occurring in both hashes
+$common = array_intersect_key($h1, $h2);
+
+// Keys occurring in the first hash [left side], but not in the second hash
+$this_not_that = array_diff_key($h1, $h2);
+
+// ----------------------------
+
+$food_colour = array('Apple' => 'red', 'Banana' => 'yellow',
+ 'Lemon' => 'yellow', 'Carrot' => 'orange');
+
+$citrus_colour = array('Lemon' => 'yellow', 'Orange' => 'orange', 'Lime' => 'green');
+
+$non_citrus = array_diff_key($food_colour, $citrus_colour);
+
+// @@PLEAC@@_5.12
+// PHP implements a special type known as a 'resource' that encompasses things like file handles,
+// sockets, database connections, and many others. The 'resource' type is, essentially, a
+// reference variable that is not readily serialisable. That is to say:
+// * A 'resource' may be converted to a string representation via the 'var_export' function
+// * That same string cannot be converted back into a 'resource'
+// So, in terms of array handling, 'resource' types may be stored as array reference values,
+// but cannot be used as keys.
+//
+// I suspect it is this type of problem that the Perl::Tie package helps resolve. However, since
+// PHP doesn't, AFAIK, sport a similar facility, the examples in this section cannot be
+// implemented using file handles as keys
+
+$filenames = array('/etc/termcap', '/vmlinux', '/bin/cat');
+
+foreach($filenames as $filename)
+{
+ if (!($fh = fopen($filename, 'r'))) continue;
+
+ // Cannot do this as required by the Perl code:
+ // $name[$fh] = $filename;
+
+ // Ok
+ $name[$filename] = $fh;
+}
+
+// Would traverse array via:
+//
+// foreach(array_keys($name) as $fh)
+// ...
+// or
+//
+// foreach($name as $fh => $filename)
+// ...
+// but since '$fh' cannot be a key, either of these will work:
+//
+// foreach($name as $filename => $fh)
+// or
+foreach(array_values($name) as $fh)
+{
+ fclose($fh);
+}
+
+// @@PLEAC@@_5.13
+// PHP hashes are dynamic expanding and contracting as entries are added, and removed,
+// respectively. Thus, there is no need to presize a hash, nor is there, AFAIK, any
+// means of doing so except by the number of datums used when defining the hash
+
+// zero elements
+$hash = array();
+
+// ------------
+
+// three elements
+$hash = array('Apple' => 'red', 'Lemon' => 'yellow', 'Carrot' => 'orange');
+
+// @@PLEAC@@_5.14
+foreach($array as $element) $count[$element] += 1;
+
+// @@PLEAC@@_5.15
+$father = array('Cain' => 'Adam', 'Abel' => 'Adam', 'Seth' => 'Adam', 'Enoch' => 'Cain',
+ 'Irad' => 'Enoch', 'Mehujael' => 'Irad', 'Methusael'=> 'Mehujael',
+ 'Lamech' => 'Methusael', 'Jabal' => 'Lamech', 'Jubal' => 'Lamech',
+ 'Tubalcain' => 'Lamech', 'Enos' => 'Seth');
+
+// ------------
+
+$name = trim(fgets(STDIN));
+
+while (!feof(STDIN))
+{
+ while (TRUE)
+ {
+ echo "$name\n";
+
+ // Can use either:
+ if (!isset($father[$name])) break;
+ $name = $father[$name];
+
+ // or:
+ // if (!key_exists($name, $father)) break;
+ // $name = $father[$name];
+
+ // or combine the two lines:
+ // if (!($name = $father[$name])) break;
+ }
+
+ echo "\n";
+ $name = trim(fgets(STDIN));
+}
+
+// ----------------------------
+
+define(SEP, ' ');
+
+foreach($father as $child => $parent)
+{
+ if (!$children[$parent])
+ $children[$parent] = $child;
+ else
+ $children[$parent] .= SEP . $child;
+}
+
+$name = trim(fgets(STDIN));
+
+while (!feof(STDIN))
+{
+ echo $name . ' begat ';
+
+ if (!$children[$name])
+ echo "Nothing\n"
+ else
+ echo str_replace(SEP, ', ', $children[$name]) . "\n";
+
+ $name = trim(fgets(STDIN));
+}
+
+// ----------------------------
+
+define(SEP, ' ');
+
+$files = array('/tmp/a', '/tmp/b', '/tmp/c');
+
+foreach($files as $file)
+{
+ if (!is_file($file)) { echo "Skipping {$file}\n"; continue; }
+ if (!($fh = fopen($file, 'r'))) { echo "Skipping {$file}\n"; continue; }
+
+ $line = fgets($fh);
+
+ while (!feof($fh))
+ {
+ if (preg_match('/^\s*#\s*include\s*<([^>]+)>/', $line, $matches))
+ {
+ if (isset($includes[$matches[1]]))
+ $includes[$matches[1]] .= SEP . $file;
+ else
+ $includes[$matches[1]] = $file;
+ }
+
+ $line = fgets($fh);
+ }
+
+ fclose($fh);
+}
+
+print_r($includes);
+
+// @@PLEAC@@_5.16
+// @@INCOMPLETE@@
+// @@INCOMPLETE@@
+
+// @@PLEAC@@_9.0
+$entry = stat('/bin/vi');
+$entry = stat('/usr/bin');
+$entry = stat($argv[1]);
+
+// ------------
+
+$entry = stat('/bin/vi');
+
+$ctime = $entry['ctime'];
+$size = $entry['size'];
+
+// ----------------------------
+
+// For the simple task of determining whether a file contains, text', a simple
+// function that searches for a newline could be implemented. Not exactly
+// foolproof, but very simple, low overhead, no installation headaches ...
+function containsText($file)
+{
+ $status = FALSE;
+
+ if (($fp = fopen($file, 'r')))
+ {
+ while (FALSE !== ($char = fgetc($fp)))
+ {
+ if ($char == "\n") { $status = TRUE; break; }
+ }
+
+ fclose($fp);
+ }
+
+ return $status;
+}
+
+// PHP offers the [currently experimental] Fileinfo group of functions to
+// determine file types based on their contents / 'magic numbers'. This
+// is functionality similar to the *NIX, 'file' utility. Note that it must
+// first be installed using the PEAR utility [see PHP documentation]
+function isTextFile($file)
+{
+ // Note: untested code, but I believe this is how it is supposed to work
+ $finfo = finfo_open(FILEINFO_NONE);
+ $status = (finfo_file($finfo, $file) == 'ASCII text');
+ finfo_close($finfo);
+ return $status;
+}
+
+// Alternatively, use the *NIX utility, 'file', directly
+function isTextFile($file)
+{
+ return exec(trim('file -bN ' . escapeshellarg($file))) == 'ASCII text';
+}
+
+// ----
+
+containsText($argv[1]) || die("File {$argv[1]} doesn't have any text in it\n");
+
+isTextFile($argv[1]) || die("File {$argv[1]} doesn't have any text in it\n");
+
+// ----------------------------
+
+$dirname = '/usr/bin/';
+
+($dirhdl = opendir($dirname)) || die("Couldn't open {$dirname}\n");
+
+while (($file = readdir($dirhdl)) !== FALSE)
+{
+ printf("Inside %s is something called: %s\n", $dirname, $file);
+}
+
+closedir($dirhdl);
+
+// @@PLEAC@@_9.1
+$filename = 'example.txt';
+
+// Get the file's current access and modification time, respectively
+$fs = stat($filename);
+
+$readtime = $fs['atime'];
+$writetime = $fs['mtime'];
+
+// Alter $writetime, and $readtime ...
+
+// Update file timestamp
+touch($filename, $writetime, $readtime);
+
+// ----------------------------
+
+$filename = 'example.txt';
+
+// Get the file's current access and modification time, respectively
+$fs = stat($filename);
+
+$atime = $fs['atime'];
+$mtime = $fs['mtime'];
+
+// Dedicated functions also exist to retrieve this information:
+//
+// $atime = $fileatime($filename);
+// $mtime = $filemtime($filename);
+//
+
+// Perform date arithmetic. Traditional approach where arithmetic is performed
+// directly with Epoch Seconds [i.e. the *NIX time stamp value] will work ...
+
+define('SECONDS_PER_DAY', 60 * 60 * 24);
+
+// Set file's access and modification times to 1 week ago
+$atime -= 7 * SECONDS_PER_DAY;
+$mtime -= 7 * SECONDS_PER_DAY;
+
+// ... but care must be taken to account for daylight saving. Therefore, the
+// recommended approach is to use library functions to perform such tasks:
+
+$atime = strtotime('-7 days', $atime);
+$mtime = strtotime('-7 days', $mtime);
+
+// Update file timestamp
+touch($filename, $mtime, $atime);
+
+// Good idea to clear the cache after such updates have occurred so fresh
+// values will be retrieved on next access
+clearstatcache();
+
+// ----------------------------
+
+$argc == 2 || die("usage: {$argv[0]} filename\n");
+
+$filename = $argv[1];
+$fs = stat($filename);
+
+$atime = $fs['atime'];
+$mtime = $fs['mtime'];
+
+// Careful here: since interactive, use, 'system', not 'exec', to launch [latter
+// does not work under *NIX - at least, not for me :)]
+system(trim(getenv('EDITOR') . ' vi ' . escapeshellarg($filename)), $retcode);
+
+touch($filename, $mtime, $atime) || die("Error updating timestamp on file, {$filename}!\n");
+
+// @@PLEAC@@_9.2
+// The 'unlink' function is used to delete regular files, whilst the 'rmdir' function
+// does the same on non-empty directories. AFAIK, no recursive-deletion facility
+// exists, and must be manually programmed
+
+$filename = '...';
+
+@unlink($filename) || die("Can't delete, {$filename}!\n");
+
+// ------------
+
+$files = glob('...');
+$problem = FALSE;
+
+// Could simply use a foreach loop
+foreach($files as $filename) { @unlink($filename) || $problem = TRUE; }
+
+//
+// Alternatively, an applicative approach could be used, one closer in spirit to
+// largely-functional languages like Scheme
+//
+// function is_all_deleted($deleted, $filename) { return @unlink($filename) && $deleted; }
+// $problem = !array_reduce($files, 'is_all_deleted', TRUE);
+//
+
+if ($problem)
+{
+ fwrite(STDERR, 'Could not delete all of:');
+ foreach($files as $filename) { fwrite(STDERR, ' ' . $filename); }
+ fwrite(STDERR, "\n"); exit(1);
+}
+
+// ------------
+
+function rmAll($files)
+{
+ $count = 0;
+
+ foreach($files as $filename) { @unlink($filename) && $count++; };
+
+ return $count;
+
+// An applicative alternative using 'create_function', PHP's rough equivalent of 'lambda' ...
+//
+// return array_reduce($files,
+// create_function('$count, $filename', 'return @unlink($filename) && $count++;'), 0);
+}
+
+// ----
+
+$files = glob('...');
+$toBeDeleted = sizeof($files);
+$count = rmAll($files);
+
+($count == $toBeDeleted) || die("Could only delete {$count} of {$toBeDeleted} files\n");
+
+// @@PLEAC@@_9.3
+$oldfile = '/tmp/old'; $newfile = '/tmp/new';
+
+copy($oldfile, $newfile) || die("Error copying file\n");
+
+// ----------------------------
+
+// All the following copy a file by copying its contents. Examples do so in a single
+// operation, but it is also possible to copy arbitrary blocks, or, line-by-line in
+// the case of 'text' files
+$oldfile = '/tmp/old'; $newfile = '/tmp/new';
+
+if (is_file($oldfile))
+ file_put_contents($newfile, file_get_contents($oldfile));
+else
+ die("Problem copying file {$oldfile} to file {$newfile}\n");
+
+// ------------
+
+$oldfile = '/tmp/old'; $newfile = '/tmp/new';
+
+fwrite(($nh = fopen($newfile, 'wb')), fread(($oh = fopen($oldfile, 'rb')), filesize($oldfile)));
+fclose($oh);
+fclose($nh);
+
+// ------------
+
+// As above, but with some error checking / handling
+$oldfile = '/tmp/old'; $newfile = '/tmp/new';
+
+($oh = fopen($oldfile, 'rb')) || die("Problem opening input file {$oldfile}\n");
+($nh = fopen($newfile, 'wb')) || die("Problem opening output file {$newfile}\n");
+
+if (($filesize = filesize($oldfile)) > 0)
+{
+ fwrite($nh, fread($oh, $filesize)) || die("Problem reading / writing file data\n");
+}
+
+fclose($oh);
+fclose($nh);
+
+// ----------------------------
+
+// Should there be platform-specfic problems copying 'very large' files, it is
+// a simple matter to call a system command utility via, 'exec'
+
+// *NIX-specific example. Could check whether, 'exec', succeeded, but checking whether
+// a file exists after the operation might be a better approach
+$oldfile = '/tmp/old'; $newfile = '/tmp/new';
+
+is_file($newfile) && unlink($newfile);
+
+exec(trim('cp --force ' . escapeshellarg($oldfile) . ' ' . escapeshellarg($newfile)));
+
+is_file($newfile) || die("Problem copying file {$oldfile} to file {$newfile}\n");
+
+// For other operating systems just change:
+// * filenames
+// * command being 'exec'ed
+// as the rest of the code is platform independant
+
+// @@PLEAC@@_9.4
+function makeDevInodePair($filename)
+{
+ if (!($fs = @stat($filename))) return FALSE;
+ return strval($fs['dev'] . $fs['ino']);
+}
+
+// ------------
+
+function do_my_thing($filename)
+{
+ // Using a global variable to mimic Perl example, but could easily have passed
+ // '$seen' as an argument
+ global $seen;
+
+ $devino = makeDevInodePair($filename);
+
+ // Process $filename if it has not previously been seen, else just increment
+ if (!isset($seen[$devino]))
+ {
+ // ... process $filename ...
+
+ // Set initial count
+ $seen[$devino] = 1;
+ }
+ else
+ {
+ // Otherwise, just increment the count
+ $seen[$devino] += 1;
+ }
+}
+
+// ----
+
+// Simple example
+$seen = array();
+
+do_my_thing('/tmp/old');
+do_my_thing('/tmp/old');
+do_my_thing('/tmp/old');
+do_my_thing('/tmp/new');
+
+foreach($seen as $devino => $count)
+{
+ echo "{$devino} -> {$count}\n";
+}
+
+// ------------
+
+// A variation on the above avoiding use of global variables, and illustrating use of
+// easily-implemented 'higher order' techniques
+
+// Helper function loosely modelled on, 'array_reduce', but using an array as
+// 'accumulator', which is returned on completion
+function array_update($arr, $lambda, $updarr)
+{
+ foreach($arr as $key) $lambda($updarr, $key);
+ return $updarr;
+}
+
+function do_my_thing(&$seen, $filename)
+{
+ if (!array_key_exists(($devino = makeDevInodePair($filename)), $seen))
+ {
+ // ... processing $filename ...
+
+ // Update $seen
+ $seen[$devino] = 1;
+ }
+ else
+ {
+ // Update $seen
+ $seen[$devino] += 1;
+ }
+}
+
+// ----
+
+// Simple example
+$files = array('/tmp/old', '/tmp/old', '/tmp/old', '/tmp/new');
+
+// Could do this ...
+$seen = array();
+array_update($files, 'do_my_thing', &$seen);
+
+// or this:
+$seen = array_update($files, 'do_my_thing', array());
+
+// or a 'lambda' could be used:
+array_update($files,
+ create_function('$seen, $filename', '... code not shown ...'),
+ &$seen);
+
+foreach($seen as $devino => $count)
+{
+ echo "{$devino} -> {$count}\n";
+}
+
+// ----------------------------
+
+$files = glob('/tmp/*');
+
+define(SEP, ';');
+$seen = array();
+
+foreach($files as $filename)
+{
+ if (!array_key_exists(($devino = makeDevInodePair($filename)), $seen))
+ $seen[$devino] = $filename;
+ else
+ $seen[$devino] = $seen[$devino] . SEP . $filename;
+}
+
+$devino = array_keys($seen);
+sort($devino);
+
+foreach($devino as $key)
+{
+ echo $key . ':';
+ foreach(split(SEP, $seen[$key]) as $filename) echo ' ' . $filename;
+ echo "\n";
+}
+
+// @@PLEAC@@_9.5
+// Conventional POSIX-like approach to directory traversal
+$dirname = '/usr/bin/';
+
+($dirhdl = opendir($dirname)) || die("Couldn't open {$dirname}\n");
+
+while (($file = readdir($dirhdl)) !== FALSE)
+{
+ ; // ... do something with $dirname/$file
+ // ...
+}
+
+closedir($dirhdl);
+
+// ------------
+
+// Newer [post PHP 4], 'applicative' approach - an array of filenames is
+// generated that may be processed via external loop ...
+
+$dirname = '/usr/bin/';
+
+foreach(scandir($dirname) as $file)
+{
+ ; // ... do something with $dirname/$file
+ // ...
+}
+
+// .. or, via callback application, perhaps after massaging by one of the
+// 'array' family of functions [also uses, 'array_update', from earlier section]
+
+$newlist = array_update(array_reverse(scandir($dirname)),
+ create_function('$filelist, $file', ' ; '),
+ array());
+
+// And don't forget that the old standby, 'glob', that returns an array of
+// paths filtered using the Bourne Shell-based wildcards, '?' and '*', is
+// also available
+
+foreach(glob($dirname . '*') as $path)
+{
+ ; // ... do something with $path
+ // ...
+}
+
+// ----------------------------
+
+// Uses, 'isTextFile', from an earlier section
+$dirname = '/usr/bin/';
+
+echo "Text files in {$dirname}:\n";
+
+foreach(scandir($dirname) as $file)
+{
+ // Take care when constructing paths to ensure cross-platform operability
+ $path = $dirname . $file;
+
+ if (is_file($path) && isTextFile($path)) echo $path . "\n";
+}
+
+// ----------------------------
+
+function plain_files($dirname)
+{
+ ($dirlist = glob($dirname . '*')) || die("Couldn't glob {$dirname}\n");
+
+ // Pass function name directly if only a single function performs filter test
+ return array_filter($dirlist, 'is_file');
+
+ // Use, 'create_function', if a multi-function test is needed
+ //
+ // return array_filter($dirlist, create_function('$path', 'return is_file($path);'));
+ //
+}
+
+// ------------
+
+foreach(plain_files('/tmp/') as $path)
+{
+ echo $path . "\n";
+}
+
+// @@PLEAC@@_9.6
+$dirname = '/tmp/';
+
+// Full paths
+$pathlist = glob($dirname . '*.c');
+
+// File names only - glob-based matching
+$filelist = array_filter(scandir($dirname),
+ create_function('$file', 'return fnmatch("*.c", $file);'));
+
+// ----------------------------
+
+$dirname = '/tmp/';
+
+// File names only - regex-based matching [case-insensitive]
+$filelist = array_filter(scandir($dirname),
+ create_function('$file', 'return eregi("\.[ch]$", $file);'));
+
+// ----------------------------
+
+$dirname = '/tmp/';
+
+// Directory names - all-digit names
+$dirs = array_filter(glob($dirname . '*', GLOB_ONLYDIR),
+ create_function('$path', 'return ereg("^[0-9]+$", basename($path));'));
+
+// @@PLEAC@@_9.7
+// Recursive directory traversal function and helper: traverses a directory tree
+// applying a function [and a variable number of accompanying arguments] to each
+// file
+
+class Accumulator
+{
+ public $value;
+ public function __construct($start_value) { $this->value = $start_value; }
+}
+
+// ------------
+
+function process_directory_($op, $func_args)
+{
+ if (is_dir($func_args[0]))
+ {
+ $current = $func_args[0];
+ foreach(scandir($current) as $entry)
+ {
+ if ($entry == '.' || $entry == '..') continue;
+ $func_args[0] = $current . '/' . $entry;
+ process_directory_($op, $func_args);
+ }
+ }
+ else
+ {
+ call_user_func_array($op, $func_args);
+ }
+}
+
+function process_directory($op, $dir)
+{
+ if (!is_dir($dir)) return FALSE;
+ $func_args = array_slice(func_get_args(), 1);
+ process_directory_($op, $func_args);
+ return TRUE;
+}
+
+// ----------------------------
+
+$dirlist = array('/tmp/d1', '/tmp/d2', '/tmp/d3');
+
+// Do something with each directory in the list
+foreach($dirlist as $dir)
+{
+ ;
+ // Delete directory [if empty] -> rmdir($dir);
+ // Make it the 'current directory' -> chdir($dir);
+ // Get list of files it contains -> $filelist = scandir($dir);
+ // Get directory metadata -> $ds = stat($dir);
+}
+
+// ------------
+
+$dirlist = array('/tmp/d1', '/tmp/d2', '/tmp/d3');
+
+function pf($path)
+{
+ // ... do something to the file or directory ...
+ printf("%s\n", $path);
+}
+
+// For each directory in the list ...
+foreach($dirlist as $dir)
+{
+ // Is this a valid directory ?
+ if (!is_dir($dir)) { printf("%s does not exist\n", $dir); continue; }
+
+ // Ok, so get all the directory's entries
+ $filelist = scandir($dir);
+
+ // An 'empty' directory will contain at least two entries: '..' and '.'
+ if (count($filelist) == 2) { printf("%s is empty\n", $dir); continue; }
+
+ // For each file / directory in the directory ...
+ foreach($filelist as $file)
+ {
+ // Ignore '..' and '.' entries
+ if ($file == '.' || $file == '..') continue;
+
+ // Apply function to process the file / directory
+ pf($dir . '/' . $file);
+ }
+}
+
+// ----------------------------
+
+function accum_filesize($file, $accum)
+{
+ is_file($file) && ($accum->value += filesize($file));
+}
+
+// ------------
+
+// Verify arguments ...
+$argc == 2 || die("usage: {$argv[0]} dir\n");
+$dir = $argv[1];
+
+is_dir($dir) || die("{$dir} does not exist / not a directory\n");
+
+// Collect data [use an object to accumulate results]
+$dirsize = new Accumulator(0);
+process_directory('accum_filesize', $dir, $dirsize);
+
+// Report results
+printf("%s contains %d bytes\n", $dir, $dirsize->value);
+
+// ----------------------------
+
+function biggest_file($file, $accum)
+{
+ if (is_file($file))
+ {
+ $fs = filesize($file);
+ if ($accum->value[1] < $fs) { $accum->value[0] = $file; $accum->value[1] = $fs; }
+ }
+}
+
+// ------------
+
+// Verify arguments ...
+$argc == 2 || die("usage: {$argv[0]} dir\n");
+$dir = $argv[1];
+
+is_dir($dir) || die("{$dir} does not exist / not a directory\n");
+
+// Collect data [use an object to accumulate results]
+$biggest = new Accumulator(array('', 0));
+process_directory('biggest_file', $dir, $biggest);
+
+// Report results
+printf("Biggest file is %s containing %d bytes\n", $biggest->value[0], $biggest->value[1]);
+
+// ----------------------------
+
+function youngest_file($file, $accum)
+{
+ if (is_file($file))
+ {
+ $fct = filectime($file);
+ if ($accum->value[1] > $fct) { $accum->value[0] = $file; $accum->value[1] = $fct; }
+ }
+}
+
+// ------------
+
+// Verify arguments ...
+$argc == 2 || die("usage: {$argv[0]} dir\n");
+$dir = $argv[1];
+
+is_dir($dir) || die("{$dir} does not exist / not a directory\n");
+
+// Collect data [use an object to accumulate results]
+$youngest = new Accumulator(array('', 2147483647));
+process_directory('youngest_file', $dir, $youngest);
+
+// Report results
+printf("Youngest file is %s dating %s\n", $youngest->value[0], date(DATE_ATOM, $youngest->value[1]));
+
+// @@PLEAC@@_9.8
+// AFAICT, there is currently no library function that recursively removes a
+// directory tree [i.e. a directory, it's subdirectories, and any other files]
+// with a single call. Such a function needs to be custom built. PHP tools
+// with which to do this:
+// * 'unlink', 'rmdir', 'is_dir', and 'is_file' functions, will all take care
+// of the file testing and deletion
+// * Actual directory traversal requires obtaining directory / subdirectory
+// lists, and here there is much choice available, though care must be taken
+// as each has it's own quirks
+// - 'opendir', 'readdir', 'closedir'
+// - 'scandir'
+// - 'glob'
+// - SPL 'directory iterator' classes [newish / experimental - not shown here]
+//
+// The PHP documentation for 'rmdir' contains several examples, each illustrating
+// one of each approach; the example shown here is loosely based on one of these
+// examples
+
+// Recursor - recursively traverses directory tree
+function rmtree_($dir)
+{
+ $dir = "$dir";
+
+ if ($dh = opendir($dir))
+ {
+ while (FALSE !== ($item = readdir($dh)))
+ {
+ if ($item != '.' && $item != '..')
+ {
+ $subdir = $dir . '/' . "$item";
+
+ if (is_dir($subdir)) rmtree_($subdir);
+ else @unlink($subdir);
+ }
+ }
+
+ closedir($dh); @rmdir($dir);
+ }
+}
+
+// Launcher - performs validation then starts recursive routine
+function rmtree($dir)
+{
+ if (is_dir($dir))
+ {
+ (substr($dir, -1, 1) == '/') && ($dir = substr($dir, 0, -1));
+ rmtree_($dir); return !is_dir($dir);
+ }
+
+ return FALSE;
+}
+
+// ------------
+
+$argc == 2 || die("usage: rmtree dir\n");
+
+rmtree($argv[1]) || die("Could not remove directory {$argv[1]}\n");
+
+// @@PLEAC@@_9.9
+$filepairs = array('x.txt' => 'x2.txt', 'y.txt' => 'y.doc', 'zxc.txt' => 'cxz.txt');
+
+foreach($filepairs as $oldfile => $newfile)
+{
+ @rename($oldfile, $newfile) || fwrite(STDERR, sprintf("Could not rename %s to %s\n", $oldfile, $newfile));
+}
+
+// ----------------------------
+
+// Call a system command utility via, 'exec'. *NIX-specific example. Could check whether,
+// 'exec', succeeded, but checking whether a renamed file exists after the operation might
+// be a better approach
+
+$oldfile = '/tmp/old'; $newfile = '/tmp/new';
+
+is_file($newfile) && unlink($newfile);
+
+exec(trim('mv --force ' . escapeshellarg($oldfile) . ' ' . escapeshellarg($newfile)));
+
+is_file($oldfile) || die("Problem renaming file {$oldfile} to file {$newfile}\n");
+
+// For other operating systems just change:
+// * filenames
+// * command being 'exec'ed
+// as the rest of the code is platform independant
+
+// ----------------------------
+
+// A modified implementation of Larry's Filename Fixer. Rather than passing
+// a single expression, a 'from' regexp is passed; each match in the file
+// name(s) is changed to the value of 'to'. It otherwise behaves the same
+//
+
+$argc > 2 || die("usage: rename from to [file ...]\n");
+
+$from = $argv[1];
+$to = $argv[2];
+
+if (count(($argv = array_slice($argv, 3))) < 1)
+ while (!feof(STDIN)) $argv[] = substr(fgets(STDIN), 0, -1);
+
+foreach($argv as $file)
+{
+ $was = $file;
+ $file = ereg_replace($from, $to, $file);
+
+ if (strcmp($was, $file) != 0)
+ @rename($was, $file) || fwrite(STDERR, sprintf("Could not rename %s to %s\n", $was, $file));
+}
+
+// @@PLEAC@@_9.10
+$base = basename($path);
+$dir = dirname($path);
+
+// PHP's equivalent to Perl's 'fileparse'
+$pathinfo = pathinfo($path);
+
+$base = $pathinfo['basename'];
+$dir = $pathinfo['dirname'];
+$ext = $pathinfo['extension'];
+
+// ----------------------------
+
+$path = '/usr/lib/libc.a';
+
+printf("dir is %s, file is %s\n", dirname($path), basename($path));
+
+// ------------
+
+$path = '/usr/lib/libc.a';
+
+$pathinfo = pathinfo($path);
+
+printf("dir is %s, name is %s, extension is %s\n", $pathinfo['dirname'], $pathinfo['basename'], $pathinfo['extension']);
+
+// ----------------------------
+
+// Handle Mac example as a simple parse task. However, AFAIK, 'pathinfo' is cross-platform,
+// so should handle file path format differences transparently
+$path = 'Hard%20Drive:System%20Folder:README.txt';
+
+$macp = array_combine(array('drive', 'folder', 'filename'), split("\:", str_replace('%20', ' ', $path)));
+$macf = array_combine(array('name', 'extension'), split("\.", $macp['filename']));
+
+printf("dir is %s, name is %s, extension is %s\n", ($macp['drive'] . ':' . $macp['folder']), $macf['name'], ('.' . $macf['extension']));
+
+// ----------------------------
+
+// Not really necessary since we have, 'pathinfo', but better matches Perl example
+function file_extension($filename, $separator = '.')
+{
+ return end(split(("\\" . $separator), $filename));
+}
+
+// ----
+
+echo file_extension('readme.txt') . "\n";
+
+// @@PLEAC@@_9.11
+// @@INCOMPLETE@@
+// @@INCOMPLETE@@
+
+// @@PLEAC@@_9.12
+// @@INCOMPLETE@@
+// @@INCOMPLETE@@
+
+// @@PLEAC@@_10.0
+// Since defined at outermost scope, $greeted may be considered a global variable
+$greeted = 0;
+
+// ------------
+
+// Must use, 'global', keyword to inform functions that $greeted already exists as
+// a global variable. If this is not done, a local variable of that name is implicitly
+// defined
+function howManyGreetings()
+{
+ global $greeted;
+ return $greeted;
+}
+
+function hello()
+{
+ global $greeted;
+ $greeted++;
+ echo "high there!, this procedure has been called {$greeted} times\n";
+}
+
+// ------------
+
+hello();
+$greetings = howManyGreetings();
+echo "bye there!, there have been {$greetings} greetings so far\n";
+
+// @@PLEAC@@_10.1
+// Conventionally-defined function together with parameter list
+function hypotenuse($side1, $side2)
+{
+ return sqrt(pow($side1, 2) + pow($side2, 2));
+}
+
+// ----
+
+// Alternative is to define the function without parameter list, then use
+// 'func_get_arg' to extract arguments
+function hypotenuse()
+{
+ // Could check number of arguments passed with: 'func_num_args', which
+ // would be the approach used if dealing with variable number of arguments
+ $side1 = func_get_arg(0); $side2 = func_get_arg(1);
+
+ return sqrt(pow($side1, 2) + pow($side2, 2));
+}
+
+// ------------
+
+// 1. Conventional function call
+$diag = hypotenuse(3, 4);
+
+// ------------
+
+// 2. Function call using, 'call_user_func' library routines
+$funcname = 'hypotenuse';
+
+// a. Pass function name, and variable number of arguments
+$diag = call_user_func($funcname, 3, 4);
+
+// b. Package arguments as array, pass together with function name
+$args = array(3, 4);
+$diag = call_user_func_array($funcname, $args);
+
+// ----------------------------
+
+$nums = array(1.4, 3.5, 6.7);
+
+// ------------
+
+// Pass-by-value
+function int_all($arr)
+{
+ return array_map(create_function('$n', 'return (int) $n;'), $arr);
+}
+
+// Pass-by-reference
+function trunc_em(&$n)
+{
+ foreach ($n as &$value) $value = (int) $value;
+}
+
+// ------------
+
+// $nums untouched; $ints is new array
+$ints = int_all($nums);
+
+// $nums updated
+trunc_em($nums);
+
+// @@PLEAC@@_10.2
+// Strictly-speaking, PHP is neither lexically [no environment capture] nor
+// dynamically [no variable shadowing] scoped. A script in which several
+// functions have been defined has two, entirely separate, scopes:
+//
+// * A 'top-level' scope i.e. everything outside each function
+//
+// * A 'local scope' within each function; each function is a self-contained
+// entity and cannot [via conventional means] access variables outside its
+// local scope. Accessing a variable that has not been locally defined
+// serves to define it i.e. accessing a variable assumed to be global
+// sees a local variable of that name defined
+//
+// The way 'global' variables are provided is via a predefined array of
+// variable names, $GLOBALS [it is one of a special set of variables known
+// as 'superglobals'; such variables *are* accessable in all scopes]. Each
+// entry in this array is a 'global' variable name, and may be freely
+// accessed / updated. A more convenient means of accessing such variables
+// is via the 'global' keyword: one or more variables within a function is
+// declared 'global', and those names are then taken to refer to entries
+// in the $GLOBALS array rather than seeing local variables of that name
+// accessed or defined
+
+function some_func()
+{
+ // Variables declared within a function are local to that function
+ $variable = 'something';
+}
+
+// ----------------------------
+
+// Top-level declared variables
+$name = $argv[1]; $age = $argv[2];
+
+$c = fetch_time();
+
+$condition = 0;
+
+// ------------
+
+function run_check()
+{
+ // The globally-declared variable, '$condition', is not accessable within
+ // the function unless it declared as 'global. Had this not been done then
+ // attempts to access, '$condition', would have seen a local variable
+ // of that name declared and updated. Same applies to other variables
+ global $condition, $name, $age, $c;
+
+ $condition = 1;
+ // ...
+}
+
+function check_x($x)
+{
+ $y = 'whatever';
+
+ // This function only has access to the parameter, '$x', and the locally
+ // declared variable, '$y'.
+
+ // Whilst 'run_check' has access to several global variables, the current
+ // function does not. For it to access the global variable, '$condition',
+ // it must be declared 'global'
+ run_check();
+
+ global $condition;
+
+ // 'run_check' will have updated, '$condition', and since it has been
+ // declared 'global' here, it is accessable
+
+ if ($condition)
+ {
+ ; // ...
+ }
+}
+
+// @@PLEAC@@_10.3
+// Local scopes are not created in the same way as in Perl [by simply enclosing
+// within braces]: only via the creation of functions are local scopes created
+
+// Doesn't create a local scope; '$myvariable' is created at top-level
+{
+ $myvariable = 7;
+}
+
+// '$myvariable' is accessable here
+echo $myvariable . "\n";
+
+// ------------
+
+{
+ $counter = 0;
+
+ // Local scope created within function, but not within surrounding braces
+ // so:
+ // * '$counter' is actually a top-level variable, so globally accessable
+ // * 'next_counter' has no implict access to '$counter'; must be granted
+ // via 'global' keyword
+
+ function next_counter() { global $counter; $counter++; }
+}
+
+// ----------------------------
+
+// PHP doesn't, AFAIK, offer an equivalent to Perl's BEGIN block. Similar
+// behaviour may be obtained by defining a class, and including such code
+// in its constructor
+
+class BEGIN
+{
+ private $myvariable;
+
+ function __construct()
+ {
+ $this->myvariable = 5;
+ }
+
+ function othersub()
+ {
+ echo $this->myvariable . "\n";
+ }
+}
+
+// ------------
+
+$b = new BEGIN();
+
+$b->othersub();
+
+// ----------------------------
+
+// PHP, like C, supports 'static' local variables, that is, those that upon
+// first access are initialised, and thence retain their value between function
+// calls. However, the 'counter' example is better implemented as a class
+
+class Counter
+{
+ private $counter;
+
+ function __construct($counter_init)
+ {
+ $this->counter = $counter_init;
+ }
+
+ function next_counter() { $this->counter++; return $this->counter; }
+ function prev_counter() { $this->counter; return $this->counter; }
+}
+
+// ------------
+
+$counter = new Counter(42);
+echo $counter->next_counter() . "\n";
+echo $counter->next_counter() . "\n";
+echo $counter->prev_counter() . "\n";
+
+// @@PLEAC@@_10.4
+// AFAICT there is no means of obtaining the name of the currently executing
+// function, or, for that matter, perform any stack / activation record,
+// inspection. It *is* possible to:
+//
+// * Obtain a list of the currently-defined functions ['get_defined_functions']
+// * Check whether a specific function exists ['function_exists']
+// * Use the 'Reflection API'
+//
+// So, to solve this problem would seem to require adopting a convention where
+// a string representing the function name is passed as an argument, or a local
+// variable [perhaps called, '$name'] is so set [contrived, and of limited use]
+
+function whoami()
+{
+ $name = 'whoami';
+ echo "I am: {$name}\n";
+}
+
+// ------------
+
+whoami();
+
+// @@PLEAC@@_10.5
+// In PHP all items exist as 'memory references' [i.e. non-modifiable pointers],
+// so when passing an item as a function argument, or returning an item from
+// a function, it is this 'memory reference' that is passed, and *not* the
+// contents of that item. Should several references to an item exist [e.g. if
+// passed to a function then at least two such references would exist in
+// different scopes] they would all be refering to the same copy of the item.
+// However, if an attempt is made to alter the item is made, a copy is made
+// and it is the copy that is altered, leaving the original intact.
+//
+// The PHP reference mechanism is used to selectively prevent this behaviour,
+// and ensure that if a change is made to an item that no copy is made, and that
+// it is the original item that is changed. Importantly, there is no efficiency
+// gain from passing function parameters using references if the parameter item
+// is not altered.
+
+// A copy of the item referred to by, '$arr', is made, and altered; original
+// remains intact
+function array_by_value($arr)
+{
+ $arr[0] = 7;
+ echo $arr[0] . "\n";
+}
+
+// No copy is made; original item referred to by, '$arr', is altered
+function array_by_ref(&$arr)
+{
+ $arr[0] = 7;
+ echo $arr[0] . "\n";
+}
+
+// ------------
+
+$arr = array(1, 2, 3);
+
+echo $arr[0] . "\n"; // output: 1
+array_by_value($arr); // output: 7
+echo $arr[0] . "\n"; // output: 1
+
+$arr = array(1, 2, 3);
+
+echo $arr[0] . "\n"; // output: 1
+array_by_ref($arr); // output: 7
+echo $arr[0] . "\n"; // output: 7
+
+// ----------------------------
+
+// Since, 'add_vecpair', does not attempt to alter either, '$x' or '$y', it makes
+// no difference whether they are 'passed by value', or 'passed by reference'
+function add_vecpair($x, $y)
+{
+ $r = array();
+ $length = count($x);
+ for($i = 0; $i < $length; $i++) $r[$i] = $x[$i] + $y[$i];
+ return $r;
+}
+
+// ...
+count($arr1) == count($arr2) || die("usage: add_vecpair ARR1 ARR2\n");
+
+// 'passed by value'
+$arr3 = add_vecpair($arr1, $arr2);
+
+// 'passed by reference' [also possible to override default 'passed by value'
+// if required]
+$arr3 = add_vecpair(&$arr1, &$arr2);
+
+// @@PLEAC@@_10.6
+// PHP can be described as a dynamically typed language because variables serve
+// as identifiers, and the same variable may refer to data of various types.
+// As such, the set of arguments passed to a function may vary in type between
+// calls, as can the type of return value. Where this is likely to occur type
+// checking should be performed either / both within the function body, and
+// when obtaining it's return value. As for Perl-style 'return context', I
+// don't believe it is supported by PHP
+
+// Can return any type
+function mysub()
+{
+ // ...
+ return 5;
+ // ...
+ return array(5);
+ // ...
+ return '5';
+}
+
+// Throw away return type [i.e. returns a 'void' type ?]
+mysub();
+
+// Check return type. Can do via:
+// * gettype($var)
+// * is_xxx e.g. is_array($var), is_muneric($var), ...
+$ret = mysub();
+
+if (is_numeric($ret))
+{
+ ; // ...
+}
+
+if (is_array($ret))
+{
+ ; // ...
+}
+
+if (is_string($ret))
+{
+ ; // ...
+}
+
+// @@PLEAC@@_10.7
+// PHP doesn't directly support named / keyword parameters, but these can be
+// easily mimiced using a class of key / value pairs, and passing a variable
+// number of arguments
+
+class KeyedValue
+{
+ public $key, $value;
+ public function __construct($key, $value) { $this->key = $key; $this->value = $value; }
+}
+
+function the_func()
+{
+ foreach (func_get_args() as $arg)
+ {
+ printf("Key: %10s|Value:%10s\n", $arg->key, $arg->value);
+ }
+}
+
+// ----
+
+the_func(new KeyedValue('name', 'Bob'),
+ new KeyedValue('age', 36),
+ new KeyedValue('income', 51000));
+
+// ----------------------------
+
+// Alternatively, an associative array of key / value pairs may be constructed.
+// With the aid of the 'extract' built-in function, the key part of this array
+// may be intsntiated to a variable name, thus more closely approximating the
+// behaviour of true named parameters
+
+function the_func($var_array)
+{
+ extract($var_array);
+
+ if (isset($name)) printf("Name: %s\n", $name);
+ if (isset($age)) printf("Age: %s\n", $age);
+ if (isset($income)) printf("Income: %s\n", $income);
+}
+
+// ----
+
+the_func(array('name' => 'Bob', 'age' => 36, 'income' => 51000));
+
+// ----------------------------
+
+class RaceTime
+{
+ public $time, $dim;
+ public function __construct($time, $dim) { $this->time = $time; $this->dim = $dim; }
+}
+
+function the_func($var_array)
+{
+ extract($var_array);
+
+ if (isset($start_time)) printf("start: %d - %s\n", $start_time->time, $start_time->dim);
+ if (isset($finish_time)) printf("finish: %d - %s\n", $finish_time->time, $finish_time->dim);
+ if (isset($incr_time)) printf("incr: %d - %s\n", $incr_time->time, $incr_time->dim);
+}
+
+// ----
+
+the_func(array('start_time' => new RaceTime(20, 's'),
+ 'finish_time' => new RaceTime(5, 'm'),
+ 'incr_time' => new RaceTime(3, 'm')));
+
+the_func(array('start_time' => new RaceTime(5, 'm'),
+ 'finish_time' => new RaceTime(30, 'm')));
+
+the_func(array('start_time' => new RaceTime(30, 'm')));
+
+// @@PLEAC@@_10.8
+// The 'list' keyword [looks like a function but is actually a special language
+// construct] may be used to perform multiple assignments from a numerically
+// indexed array of values, and offers the added bonus of being able to skip
+// assignment of one, or more, of those values
+
+function func() { return array(3, 6, 9); }
+
+// ------------
+
+list($a, $b, $c) = array(6, 7, 8);
+
+// Provided 'func' returns an numerically-indexed array, the following
+// multiple assignment will work
+list($a, $b, $c) = func();
+
+// Any existing variables no longer wanted would need to be 'unset'
+unset($b);
+
+// As above, but second element of return array discarded
+list($a,,$c) = func();
+
+// ----------------------------
+
+// Care needed to ensure returned array is numerically-indexed
+list($dev, $ino,,,$uid) = array_slice(array_values(stat($filename)), 0, 13);
+
+// @@PLEAC@@_10.9
+// Multiple return values are possible via packing a set of values within a
+// numerically-indexed array and using 'list' to extract them
+
+function some_func() { return array(array(1, 2, 3), array('a' => 1, 'b' => 2)); }
+
+// ------------
+
+list($arr, $hash) = some_func();
+
+// ----------------------------
+
+function some_func(&$arr, &$hash) { return array($arr, $hash); }
+
+// ------------
+
+$arrin = array(1, 2, 3); $hashin = array('a' => 1, 'b' => 2);
+
+list($arr, $hash) = some_func($arrin, $hashin);
+
+// @@PLEAC@@_10.10
+// AFAICT, most of the PHP library functions are designed to return some required
+// value on success, and FALSE on exit. Whilst it is possible to return NULL, or
+// one of the recognised 'empty' values [e.g. '' or 0 or an empty array etc],
+// FALSE actually seems to be the preferred means of indicating failure
+
+function a_func() { return FALSE; }
+
+a_func() || die("Function failed\n");
+
+if (!a_func()) die("Function failed\n");
+
+// @@PLEAC@@_10.11
+// Whether PHP is seen to support prototyping depends on the accepted
+// definition of this term:
+//
+// * Prototyping along the lines used in Ada, Modula X, and even C / C++,
+// in which a function's interface is declared separately from its
+// implementation, is *not* supported
+//
+// * Prototyping in which, as part of the function definition, parameter
+// information must be supplied. In PHP a function definition neither
+// parameter, nor return type, information needs to be supplied, though
+// it is usual to see a parameter list supplied [indicates the number,
+// positional order, and optionally, whether a parameter is passed by
+// reference; no type information is present]. In short, prototyping in
+// PHP is optional, and limited
+
+function func_with_one_arg($arg1)
+{
+ ; // ...
+}
+
+function func_with_two_arg($arg1, $arg2)
+{
+ ; // ...
+}
+
+function func_with_three_arg($arg1, $arg2, $arg3)
+{
+ ; // ...
+}
+
+// The following may be interpreted as meaning a function accepting no
+// arguments:
+function func_with_no_arg()
+{
+ ; // ...
+}
+
+// whilst the following may mean a function taking zero or more arguments
+function func_with_no_arg_information()
+{
+ ; // ...
+}
+
+// @@PLEAC@@_10.12
+// Unlike in Perl, PHP's 'die' [actually an alias for 'exit'] doesn't throw
+// an exception, but instead terminates the script, optionally either
+// returning an integer value to the operating system, or printing a message.
+// So, the following, does not exhibit the same behaviour as the Perl example
+
+die("some message\n");
+
+// Instead, like so many modern languages, PHP implements exception handling
+// via the 'catch' and 'throw' keywords. Furthermore, a C++ or Java programmer
+// would find PHP's exception handling facility remarkably similar to those
+// of their respective languages. A simple, canonical example follows:
+
+// Usual to derive new exception classes from the built-in, 'Exception',
+// class
+class MyException extends Exception
+{
+ // ...
+}
+
+// ...
+
+try
+{
+ // ...
+ if ($some_problem_detected) throw new MyException('some message', $some_error_code);
+ // ..
+}
+
+catch (MyException $e)
+{
+ ; // ... handle the problem ...
+}
+
+// ----------------------------
+
+class FullMoonException extends Exception
+{
+ // ...
+}
+
+// ...
+
+try
+{
+ // ...
+ if ($some_problem_detected) throw new FullMoonException('...', $full_moon_error_code);
+ // ..
+}
+
+catch (FullMoonException $e)
+{
+ // ... rethrow the exception - will propagate to higher level ...
+ throw $e;
+}
+
+// @@PLEAC@@_10.13
+// Please refer to discussion about PHP scope in section two of this chapter.
+// Briefly, PHP assumes a variable name within a function to be local unless
+// it has been specifically declared with the, 'global', keyword, in which
+// case it refers to a variable in the 'superglobal' array, '$GLOBALS'. Thus,
+// inadvertant variable name shadowing cannot occur since it is it not possible
+// to use the same name to refer to both a local and a global variable. If
+// accessing a global variable care should be taken to not accidentally update
+// it. The techniques used in this section are simply not required.
+
+// *** NOT TRANSLATED ***
+
+// @@PLEAC@@_10.14
+// In PHP once a function has been defined it remains defined. In other words,
+// it cannot be undefined / deleted, nor can that particular function name be
+// reused to reference another function body. Even the lambda-like functions
+// created via the 'create_function' built-in, cannot be undefined [they exist
+// until script termination, thus creating too many of these can actually
+// exhaust memory !]. However, since the latter can be assigned to variables,
+// the same variable name can be used to reference difference functions [and
+// when this is done the reference to the previous function is lost (unless
+// deliberately saved), though the function itself continues to exist].
+//
+// If, however, all that is needed is a simple function aliasing facility,
+// then just assign the function name to a variable, and execute using the
+// variable name
+
+// Original function
+function expand() { echo "expand\n"; }
+
+// Prove that function exists
+echo (function_exists('expand') ? 'yes' : 'no') . "\n";
+
+// Use a variable to alias it
+$grow = 'expand';
+
+// Call function via original name, and variable, respectively
+expand();
+
+$grow();
+
+// Remove alias variable
+unset($grow);
+
+// ----------------------------
+
+function fred() { echo "fred\n"; }
+
+$barney = 'fred';
+
+$barney();
+
+unset($barney);
+
+fred();
+
+// ------------
+
+$fred = create_function('', 'echo "fred\n";');
+
+$barney = $fred;
+
+$barney();
+
+unset($barney);
+
+$fred();
+
+// ----------------------------
+
+function red($text) { return "<FONT COLOR='red'>$text</FONT>"; }
+
+echo red('careful here') . "\n";
+
+// ------------
+
+$colour = 'red';
+
+$$colour = create_function('$text', 'global $colour;
+return "<FONT COLOR=\'$colour\'>$text</FONT>";');
+
+echo $$colour('careful here') . "\n";
+
+unset($$colour);
+
+// ----
+
+$colours = split(' ', 'red blue green yellow orange purple violet');
+
+foreach ($colours as $colour)
+{
+ $$colour = create_function('$text', 'global $colour;
+ return "<FONT COLOR=\'$colour\'>$text</FONT>";');
+}
+
+foreach ($colours as $colour) { echo $$colour("Careful with this $colour, James") . "\n"; }
+
+foreach ($colours as $colour) { unset($$colour); }
+
+// @@PLEAC@@_10.15
+// PHP sports an AUTOLOAD facility that is quite easy to use, but, AFAICT, is geared
+// towards the detection of unavailable classes rather than for individual functions.
+// Here is a rudimentary example:
+
+function __autoload($classname)
+{
+ if (!file_exists($classname))
+ {
+ // Class file does not exist, so handle situation; in this case,
+ // issue error message, and exit program
+ die("File for class: {$classname} not found - aborting\n");
+ }
+ else
+ {
+ // Class file exists, so load it
+ require_once $classname;
+ }
+}
+
+// ------------
+
+// Attempt to instantiate object of undefined class
+new UnknownClassObject();
+
+// Execution continues here if class exists
+// ...
+
+// ----------------------------
+
+// It is also possible to perform [quite extensive] introspection on functions,
+// variables etc, so it is possible to check whether a function exists before
+// executing it, thus allowing a non-existent functions to be searched for and
+// loaded from a source file, or perhaps dynamically defined. An example of what
+// could be described as a custom autoload facility appears below.
+
+$colours = array('red', 'blue', 'green', 'yellow', 'orange', 'purple', 'violet');
+
+foreach ($colours as $colour)
+{
+ $$colour = create_function('$text', 'global $colour;
+ return "<FONT COLOR=\'$colour\'>$text</FONT>";');
+}
+
+// Let's add a new colour to the list
+array_push($colours, 'chartreuse');
+
+foreach ($colours as $colour)
+{
+ // Checking whether function is defined
+ if (!function_exists($$colour))
+ {
+ // Doesn't exist, so dynamically define it
+ $$colour = create_function('$text', 'global $colour;
+ return "<FONT COLOR=\'$colour\'>$text</FONT>";');
+
+ // Alternatively, if it exists in a source file, 'include' the file:
+ // include 'newcolours.php'
+ }
+
+ echo $$colour("Careful with this $colour, James") . "\n";
+}
+
+foreach ($colours as $colour) unset($$colour);
+
+// @@PLEAC@@_10.16
+// *** Warning *** Whilst PHP *does* allow functions to be defined within other
+// functions it needs to be clearly understood that these 'inner' functions:
+// * Do not exist until the outer function is called a first time, at which time
+// they then remain defined
+// * Are global in scope, so are accessable outside the function by their name;
+// the fact that they are nested within another function has, AFAICT, no bearing
+// on name resolution
+// * Do not form a closure: the inner function is merely 'parked' within the
+// outer function, and has no implicit access to the outer function's variables
+// or other inner functions
+
+function outer($arg)
+{
+ $x = $arg + 35;
+ function inner() { return $x * 19; }
+
+ // *** wrong *** 'inner' returns 0 * 19, not ($arg + 35) * 19
+ return $x + inner();
+}
+
+// ----------------------------
+
+function outer($arg)
+{
+ $x = $arg + 35;
+
+ // No implicit access to outer function scope; any required data must be
+ // explicity passed
+ function inner($x) { return $x * 19; }
+
+ return $x + inner($x);
+}
+
+// ------------
+
+// Equivalent to previously-shown code
+function inner($x)
+{
+ return $x * 19;
+}
+
+function outer($arg)
+{
+ $x = $arg + 35;
+ return $x + inner($x);
+}
+
+// @@PLEAC@@_10.17
+// @@INCOMPLETE@@
+// @@INCOMPLETE@@
+
+// @@PLEAC@@_16.1
+// Run a command and return its results as a string.
+$output_string = shell_exec('program args');
+
+// Same as above, using backtick operator.
+$output_string = `program args`;
+
+// Run a command and return its results as a list of strings,
+// one per line.
+$output_lines = array();
+exec('program args', $output_lines);
+
+// -----------------------------
+
+// The only way to execute a program without using the shell is to
+// use pcntl_exec(). However, there is no way to do redirection, so
+// you can't capture its output.
+
+$pid = pcntl_fork();
+if ($pid == -1) {
+ die('cannot fork');
+} elseif ($pid) {
+ pcntl_waitpid($pid, $status);
+} else {
+ // Note that pcntl_exec() automatically prepends the program name
+ // to the array of arguments; the program name cannot be spoofed.
+ pcntl_exec($program, array($arg1, $arg2));
+}
+
+// @@PLEAC@@_16.2
+// Run a simple command and retrieve its result code.
+exec("vi $myfile", $output, $result_code);
+
+// -----------------------------
+
+// Use the shell to perform redirection.
+exec('cmd1 args | cmd2 | cmd3 >outfile');
+exec('cmd args <infile >outfile 2>errfile');
+
+// -----------------------------
+
+// Run a command, handling its result code or signal.
+$pid = pcntl_fork();
+if ($pid == -1) {
+ die('cannot fork');
+} elseif ($pid) {
+ pcntl_waitpid($pid, $status);
+ if (pcntl_wifexited($status)) {
+ $status = pcntl_wexitstatus($status);
+ echo "program exited with status $status\n";
+ } elseif (pcntl_wifsignaled($status)) {
+ $signal = pcntl_wtermsig($status);
+ echo "program killed by signal $signal\n";
+ } elseif (pcntl_wifstopped($status)) {
+ $signal = pcntl_wstopsig($status);
+ echo "program stopped by signal $signal\n";
+ }
+} else {
+ pcntl_exec($program, $args);
+}
+
+// -----------------------------
+
+// Run a command while blocking interrupt signals.
+$pid = pcntl_fork();
+if ($pid == -1) {
+ die('cannot fork');
+} elseif ($pid) {
+ // parent catches INT and berates user
+ declare(ticks = 1);
+ function handle_sigint($signal) {
+ echo "Tsk tsk, no process interruptus\n";
+ }
+ pcntl_signal(SIGINT, 'handle_sigint');
+ while (!pcntl_waitpid($pid, $status, WNOHANG)) {}
+} else {
+ // child ignores INT and does its thing
+ pcntl_signal(SIGINT, SIG_IGN);
+ pcntl_exec('/bin/sleep', array('10'));
+}
+
+// -----------------------------
+
+// Since there is no direct access to execv() and friends, and
+// pcntl_exec() won't let us supply an alternate program name
+// in the argument list, there is no way to run a command with
+// a different name in the process table.
+
+// @@PLEAC@@_16.3
+// Transfer control to the shell to run another program.
+pcntl_exec('/bin/sh', array('-c', 'archive *.data'));
+// Transfer control directly to another program.
+pcntl_exec('/path/to/archive', array('accounting.data'));
+
+// @@PLEAC@@_16.4
+// Handle each line in the output of a process.
+$readme = popen('program arguments', 'r');
+while (!feof($readme)) {
+ $line = fgets($readme);
+ if ($line === false) break;
+ // ...
+}
+pclose($readme);
+
+// -----------------------------
+
+// Write to the input of a process.
+$writeme = popen('program arguments', 'w');
+fwrite($writeme, 'data');
+pclose($writeme);
+
+// -----------------------------
+
+// Wait for a process to complete.
+$f = popen('sleep 1000000', 'r'); // child goes to sleep
+pclose($f); // and parent goes to lala land
+
+// -----------------------------
+
+$writeme = popen('program arguments', 'w');
+fwrite($writeme, "hello\n"); // program will get hello\n on STDIN
+pclose($writeme); // program will get EOF on STDIN
+
+// -----------------------------
+
+// Output buffering callback that sends output to the pager.
+function ob_pager($output, $mode) {
+ static $pipe;
+ if ($mode & PHP_OUTPUT_HANDLER_START) {
+ $pager = getenv('PAGER');
+ if (!$pager) $pager = '/usr/bin/less'; // XXX: might not exist
+ $pipe = popen($pager, 'w');
+ }
+ fwrite($pipe, $output);
+ if ($mode & PHP_OUTPUT_HANDLER_END) {
+ pclose($pipe);
+ }
+}
+
+// Redirect standard output to the pager.
+ob_start('ob_pager');
+
+// Do something useful that writes to standard output, then
+// close the output buffer.
+// ...
+ob_end_flush();
+
+// @@PLEAC@@_16.5
+// Output buffering: Only display a certain number of lines of output.
+class Head {
+ function Head($lines=20) {
+ $this->lines = $lines;
+ }
+
+ function filter($output, $mode) {
+ $result = array();
+ $newline = '';
+ if (strlen($output) > 0 && $output[strlen($output) - 1] == "\n") {
+ $newline = "\n";
+ $output = substr($output, 0, -1);
+ }
+ foreach (explode("\n", $output) as $i => $line) {
+ if ($this->lines > 0) {
+ $this->lines--;
+ $result[] = $line;
+ }
+ }
+ return $result ? implode("\n", $result) . $newline : '';
+ }
+}
+
+// Output buffering: Prepend line numbers to each line of output.
+class Number {
+ function Number() {
+ $this->line_number = 0;
+ }
+
+ function filter($output, $mode) {
+ $result = array();
+ $newline = '';
+ if (strlen($output) > 0 && $output[strlen($output) - 1] == "\n") {
+ $newline = "\n";
+ $output = substr($output, 0, -1);
+ }
+ foreach (explode("\n", $output) as $i => $line) {
+ $this->line_number++;
+ $result[] = $this->line_number . ': ' . $line;
+ }
+ return implode("\n", $result) . $newline;
+ }
+}
+
+// Output buffering: Prepend "> " to each line of output.
+class Quote {
+ function Quote() {
+ }
+
+ function filter($output, $mode) {
+ $result = array();
+ $newline = '';
+ if (strlen($output) > 0 && $output[strlen($output) - 1] == "\n") {
+ $newline = "\n";
+ $output = substr($output, 0, -1);
+ }
+ foreach (explode("\n", $output) as $i => $line) {
+ $result[] = "> $line";
+ }
+ return implode("\n", $result) . $newline;
+ }
+}
+
+// Use arrays as callbacks to register filter methods.
+ob_start(array(new Head(100), 'filter'));
+ob_start(array(new Number(), 'filter'));
+ob_start(array(new Quote(), 'filter'));
+
+// Act like /bin/cat.
+while (!feof(STDIN)) {
+ $line = fgets(STDIN);
+ if ($line === false) break;
+ echo $line;
+}
+
+// Should match number of calls to ob_start().
+ob_end_flush();
+ob_end_flush();
+ob_end_flush();
+
+// @@PLEAC@@_16.6
+// Process command-line arguments using fopen(). PHP supports URLs for
+// filenames as long as the "allow_url_fopen" configuration option is set.
+//
+// Valid URL protocols include:
+// - http://www.myserver.com/myfile.html
+// - ftp://ftp.myserver.com/myfile.txt
+// - compress.zlib://myfile.gz
+// - php://stdin
+//
+// See http://www.php.net/manual/en/wrappers.php for details.
+//
+$filenames = array_slice($argv, 1);
+if (!$filenames) $filenames = array('php://stdin');
+foreach ($filenames as $filename) {
+ $handle = @fopen($filename, 'r');
+ if ($handle) {
+ while (!feof($handle)) {
+ $line = fgets($handle);
+ if ($line === false) break;
+ // ...
+ }
+ fclose($handle);
+ } else {
+ die("can't open $filename\n");
+ }
+}
+
+// @@PLEAC@@_16.7
+$output = `cmd 2>&1`; // with backticks
+// or
+$ph = popen('cmd 2>&1'); // with an open pipe
+while (!feof($ph)) { $line = fgets($ph); } // plus a read
+// -----------------------------
+$output = `cmd 2>/dev/null`; // with backticks
+// or
+$ph = popen('cmd 2>/dev/null'); // with an open pipe
+while (!feof($ph)) { $line = fgets($ph); } // plus a read
+// -----------------------------
+$output = `cmd 2>&1 1>/dev/null`; // with backticks
+// or
+$ph = popen('cmd 2>&1 1>/dev/null'); // with an open pipe
+while (!feof($ph)) { $line = fgets($ph); } // plus a read
+// -----------------------------
+$output = `cmd 3>&1 1>&2 2>&3 3>&-`; // with backticks
+// or
+$ph = popen('cmd 3>&1 1>&2 2>&3 3>&-|'); // with an open pipe
+while (!feof($ph)) { $line = fgets($ph); } // plus a read
+// -----------------------------
+exec('program args 1>/tmp/program.stdout 2>/tmp/program.stderr');
+// -----------------------------
+$output = `cmd 3>&1 1>&2 2>&3 3>&-`;
+// -----------------------------
+$fd3 = $fd1;
+$fd1 = $fd2;
+$fd2 = $fd3;
+$fd3 = null;
+// -----------------------------
+exec('prog args 1>tmpfile 2>&1');
+exec('prog args 2>&1 1>tmpfile');
+// -----------------------------
+// exec('prog args 1>tmpfile 2>&1');
+$fd1 = "tmpfile"; // change stdout destination first
+$fd2 = $fd1; // now point stderr there, too
+// -----------------------------
+// exec('prog args 2>&1 1>tmpfile');
+$fd2 = $fd1; // stderr same destination as stdout
+$fd1 = "tmpfile"; // but change stdout destination
+
+// @@PLEAC@@_16.8
+// Connect to input and output of a process.
+$proc = proc_open($program,
+ array(0 => array('pipe', 'r'),
+ 1 => array('pipe', 'w')),
+ $pipes);
+if (is_resource($proc)) {
+ fwrite($pipes[0], "here's your input\n");
+ fclose($pipes[0]);
+ echo stream_get_contents($pipes[1]);
+ fclose($pipes[1]);
+ $result_code = proc_close($proc);
+ echo "$result_code\n";
+}
+
+// -----------------------------
+
+$all = array();
+$outlines = array();
+$errlines = array();
+exec("( $cmd | sed -e 's/^/stdout: /' ) 2>&1", $all);
+foreach ($all as $line) {
+ $pos = strpos($line, 'stdout: ');
+ if ($pos !== false && $pos == 0) {
+ $outlines[] = substr($line, 8);
+ } else {
+ $errlines[] = $line;
+ }
+}
+print("STDOUT:\n");
+print_r($outlines);
+print("\n");
+print("STDERR:\n");
+print_r($errlines);
+print("\n");
+
+// @@PLEAC@@_16.9
+$proc = proc_open($cmd,
+ array(0 => array('pipe', 'r'),
+ 1 => array('pipe', 'w'),
+ 2 => array('pipe', 'w')),
+ $pipes);
+
+if (is_resource($proc)) {
+ // give end of file to kid, or feed him
+ fclose($pipes[0]);
+
+ // read till EOF
+ $outlines = array();
+ while (!feof($pipes[1])) {
+ $line = fgets($pipes[1]);
+ if ($line === false) break;
+ $outlines[] = rtrim($line);
+ }
+
+ // XXX: block potential if massive
+ $errlines = array();
+ while (!feof($pipes[2])) {
+ $line = fgets($pipes[2]);
+ if ($line === false) break;
+ $errlines[] = rtrim($line);
+ }
+
+ fclose($pipes[1]);
+ fclose($pipes[2]);
+ proc_close($proc);
+
+ print("STDOUT:\n");
+ print_r($outlines);
+ print("\n");
+ print("STDERR:\n");
+ print_r($errlines);
+ print("\n");
+}
+
+// -----------------------------
+
+// cmd3sel - control all three of kids in, out, and error.
+$cmd = "grep vt33 /none/such - /etc/termcap";
+$proc = proc_open($cmd,
+ array(0 => array('pipe', 'r'),
+ 1 => array('pipe', 'w'),
+ 2 => array('pipe', 'w')),
+ $pipes);
+
+if (is_resource($proc)) {
+ fwrite($pipes[0], "This line has a vt33 lurking in it\n");
+ fclose($pipes[0]);
+
+ $readers = array($pipes[1], $pipes[2]);
+ while (stream_select($read=$readers,
+ $write=null,
+ $except=null,
+ 0, 200000) > 0) {
+ foreach ($read as $stream) {
+ $line = fgets($stream);
+ if ($line !== false) {
+ if ($stream === $pipes[1]) {
+ print "STDOUT: $line";
+ } else {
+ print "STDERR: $line";
+ }
+ }
+ if (feof($stream)) {
+ $readers = array_diff($readers, array($stream));
+ }
+ }
+ }
+
+ fclose($pipes[1]);
+ fclose($pipes[2]);
+ proc_close($proc);
+}
+
+// @@PLEAC@@_16.10
+// PHP supports fork/exec/wait but not pipe. However, it does
+// support socketpair, which can do everything pipes can as well
+// as bidirectional communication. The original recipes have been
+// modified here to use socketpair only.
+
+// -----------------------------
+
+// pipe1 - use socketpair and fork so parent can send to child
+$sockets = array();
+if (!socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets)) {
+ die(socket_strerror(socket_last_error()));
+}
+list($reader, $writer) = $sockets;
+
+$pid = pcntl_fork();
+if ($pid == -1) {
+ die('cannot fork');
+} elseif ($pid) {
+ socket_close($reader);
+ $line = sprintf("Parent Pid %d is sending this\n", getmypid());
+ if (!socket_write($writer, $line, strlen($line))) {
+ socket_close($writer);
+ die(socket_strerror(socket_last_error()));
+ }
+ socket_close($writer);
+ pcntl_waitpid($pid, $status);
+} else {
+ socket_close($writer);
+ $line = socket_read($reader, 1024, PHP_NORMAL_READ);
+ printf("Child Pid %d just read this: `%s'\n", getmypid(), rtrim($line));
+ socket_close($reader); // this will happen anyway
+ exit(0);
+}
+
+// -----------------------------
+
+// pipe2 - use socketpair and fork so child can send to parent
+$sockets = array();
+if (!socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets)) {
+ die(socket_strerror(socket_last_error()));
+}
+list($reader, $writer) = $sockets;
+
+$pid = pcntl_fork();
+if ($pid == -1) {
+ die('cannot fork');
+} elseif ($pid) {
+ socket_close($writer);
+ $line = socket_read($reader, 1024, PHP_NORMAL_READ);
+ printf("Parent Pid %d just read this: `%s'\n", getmypid(), rtrim($line));
+ socket_close($reader);
+ pcntl_waitpid($pid, $status);
+} else {
+ socket_close($reader);
+ $line = sprintf("Child Pid %d is sending this\n", getmypid());
+ if (!socket_write($writer, $line, strlen($line))) {
+ socket_close($writer);
+ die(socket_strerror(socket_last_error()));
+ }
+ socket_close($writer); // this will happen anyway
+ exit(0);
+}
+
+// -----------------------------
+
+// pipe3 and pipe4 demonstrate the use of perl's "forking open"
+// feature to reimplement pipe1 and pipe2. pipe5 uses two pipes
+// to simulate socketpair. Since PHP supports socketpair but not
+// pipe, and does not have a "forking open" feature, these
+// examples are skipped here.
+
+// -----------------------------
+
+// pipe6 - bidirectional communication using socketpair
+$sockets = array();
+if (!socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets)) {
+ die(socket_strerror(socket_last_error()));
+}
+list($child, $parent) = $sockets;
+
+$pid = pcntl_fork();
+if ($pid == -1) {
+ die('cannot fork');
+} elseif ($pid) {
+ socket_close($parent);
+ $line = sprintf("Parent Pid %d is sending this\n", getmypid());
+ if (!socket_write($child, $line, strlen($line))) {
+ socket_close($child);
+ die(socket_strerror(socket_last_error()));
+ }
+ $line = socket_read($child, 1024, PHP_NORMAL_READ);
+ printf("Parent Pid %d just read this: `%s'\n", getmypid(), rtrim($line));
+ socket_close($child);
+ pcntl_waitpid($pid, $status);
+} else {
+ socket_close($child);
+ $line = socket_read($parent, 1024, PHP_NORMAL_READ);
+ printf("Child Pid %d just read this: `%s'\n", getmypid(), rtrim($line));
+ $line = sprintf("Child Pid %d is sending this\n", getmypid());
+ if (!socket_write($parent, $line, strlen($line))) {
+ socket_close($parent);
+ die(socket_strerror(socket_last_error()));
+ }
+ socket_close($parent);
+ exit(0);
+}
+
+// @@PLEAC@@_16.11
+// -----------------------------
+// % mkfifo /path/to/named.pipe
+// -----------------------------
+
+$fifo = fopen('/path/to/named.pipe', 'r');
+if ($fifo !== false) {
+ while (!feof($fifo)) {
+ $line = fgets($fifo);
+ if ($line === false) break;
+ echo "Got: $line";
+ }
+ fclose($fifo);
+} else {
+ die('could not open fifo for read');
+}
+
+// -----------------------------
+
+$fifo = fopen('/path/to/named.pipe', 'w');
+if ($fifo !== false) {
+ fwrite($fifo, "Smoke this.\n");
+ fclose($fifo);
+} else {
+ die('could not open fifo for write');
+}
+
+// -----------------------------
+// % mkfifo ~/.plan # isn't this everywhere yet?
+// % mknod ~/.plan p # in case you don't have mkfifo
+// -----------------------------
+
+// dateplan - place current date and time in .plan file
+while (true) {
+ $home = getenv('HOME');
+ $fifo = fopen("$home/.plan", 'w');
+ if ($fifo === false) {
+ die("Couldn't open $home/.plan for writing.\n");
+ }
+ fwrite($fifo,
+ 'The current time is '
+ . strftime('%a, %d %b %Y %H:%M:%S %z')
+ . "\n");
+ fclose($fifo);
+ sleep(1);
+}
+
+// -----------------------------
+
+// fifolog - read and record log msgs from fifo
+
+$fifo = null;
+
+declare(ticks = 1);
+function handle_alarm($signal) {
+ global $fifo;
+ if ($fifo) fclose($fifo); // move on to the next queued process
+}
+pcntl_signal(SIGALRM, 'handle_alarm');
+
+while (true) {
+ pcntl_alarm(0); // turn off alarm for blocking open
+ $fifo = fopen('/tmp/log', 'r');
+ if ($fifo === false) {
+ die("can't open /tmp/log");
+ }
+ pcntl_alarm(1); // you have 1 second to log
+
+ $service = fgets($fifo);
+ if ($service === false) continue; // interrupt or nothing logged
+ $service = rtrim($service);
+
+ $message = fgets($fifo);
+ if ($message === false) continue; // interrupt or nothing logged
+ $message = rtrim($message);
+
+ pcntl_alarm(0); // turn off alarms for message processing
+
+ if ($service == 'http') {
+ // ignoring
+ } elseif ($service == 'login') {
+ // log to /var/log/login
+ $log = fopen('/var/log/login', 'a');
+ if ($log !== false) {
+ fwrite($log,
+ strftime('%a, %d %b %Y %H:%M:%S %z')
+ . " $service $message\n");
+ fclose($log);
+ } else {
+ trigger_error("Couldn't log $service $message to /var/log/login\n",
+ E_USER_WARNING);
+ }
+ }
+}
+
+// @@PLEAC@@_16.12
+// sharetest - test shared variables across forks
+
+$SHM_KEY = ftok(__FILE__, chr(1));
+$handle = sem_get($SHM_KEY);
+$buffer = shm_attach($handle, 1024);
+
+// The original recipe has an INT signal handler here. However, it
+// causes erratic behavior with PHP, and PHP seems to do the right
+// thing without it.
+
+for ($i = 0; $i < 10; $i++) {
+ $child = pcntl_fork();
+ if ($child == -1) {
+ die('cannot fork');
+ } elseif ($child) {
+ $kids[] = $child; // in case we care about their pids
+ } else {
+ squabble();
+ exit();
+ }
+}
+
+while (true) {
+ print 'Buffer is ' . shm_get_var($buffer, 1) . "\n";
+ sleep(1);
+}
+die('Not reached');
+
+function squabble() {
+ global $handle;
+ global $buffer;
+ $i = 0;
+ $pid = getmypid();
+ while (true) {
+ if (preg_match("/^$pid\\b/", shm_get_var($buffer, 1))) continue;
+ sem_acquire($handle);
+ $i++;
+ shm_put_var($buffer, 1, "$pid $i");
+ sem_release($handle);
+ }
+}
+
+// Buffer is 14357 1
+// Buffer is 14355 3
+// Buffer is 14355 4
+// Buffer is 14354 5
+// Buffer is 14353 6
+// Buffer is 14351 8
+// Buffer is 14351 9
+// Buffer is 14350 10
+// Buffer is 14348 11
+// Buffer is 14348 12
+// Buffer is 14357 10
+// Buffer is 14357 11
+// Buffer is 14355 13
+// ...
+
+// @@PLEAC@@_16.13
+// Available signal constants
+% php -r 'print_r(get_defined_constants());' | grep '\[SIG' | grep -v _
+ [SIGHUP] => 1
+ [SIGINT] => 2
+ [SIGQUIT] => 3
+ [SIGILL] => 4
+ [SIGTRAP] => 5
+ [SIGABRT] => 6
+ [SIGIOT] => 6
+ [SIGBUS] => 7
+ [SIGFPE] => 8
+ [SIGKILL] => 9
+ [SIGUSR1] => 10
+ [SIGSEGV] => 11
+ [SIGUSR2] => 12
+ [SIGPIPE] => 13
+ [SIGALRM] => 14
+ [SIGTERM] => 15
+ [SIGSTKFLT] => 16
+ [SIGCLD] => 17
+ [SIGCHLD] => 17
+ [SIGCONT] => 18
+ [SIGSTOP] => 19
+ [SIGTSTP] => 20
+ [SIGTTIN] => 21
+ [SIGTTOU] => 22
+ [SIGURG] => 23
+ [SIGXCPU] => 24
+ [SIGXFSZ] => 25
+ [SIGVTALRM] => 26
+ [SIGPROF] => 27
+ [SIGWINCH] => 28
+ [SIGPOLL] => 29
+ [SIGIO] => 29
+ [SIGPWR] => 30
+ [SIGSYS] => 31
+ [SIGBABY] => 31
+
+// Predefined signal handler constants
+% php -r 'print_r(get_defined_constants());' | grep '\[SIG' | grep _
+ [SIG_IGN] => 1
+ [SIG_DFL] => 0
+ [SIG_ERR] => -1
+
+// @@PLEAC@@_16.14
+// send pid a signal 9
+posix_kill($pid, 9);
+// send whole job a signal 1
+posix_kill($pgrp, -1);
+// send myself a SIGUSR1
+posix_kill(getmypid(), SIGUSR1);
+// send a SIGHUP to processes in pids
+foreach ($pids as $pid) posix_kill($pid, SIGHUP);
+
+// -----------------------------
+
+// Use kill with pseudo-signal 0 to see if process is alive.
+if (posix_kill($minion, 0)) {
+ echo "$minion is alive!\n";
+} else {
+ echo "$minion is deceased.\n";
+}
+
+// @@PLEAC@@_16.15
+// call got_sig_quit for every SIGQUIT
+pcntl_signal(SIGQUIT, 'got_sig_quit');
+// call got_sig_pipe for every SIGPIPE
+pcntl_signal(SIGPIPE, 'got_sig_pipe');
+// increment ouch for every SIGINT
+function got_sig_int($signal) { global $ouch; $ouch++; }
+pcntl_signal(SIGINT, 'got_sig_int');
+// ignore the signal INT
+pcntl_signal(SIGINT, SIG_IGN);
+// restore default STOP signal handling
+pcntl_signal(SIGSTOP, SIG_DFL);
+
+// @@PLEAC@@_16.16
+// the signal handler
+function ding($signal) {
+ fwrite(STDERR, "\x07Enter your name!\n");
+}
+
+// prompt for name, overriding SIGINT
+function get_name() {
+ declare(ticks = 1);
+ pcntl_signal(SIGINT, 'ding');
+
+ echo "Kindly Stranger, please enter your name: ";
+ while (!@stream_select($read=array(STDIN),
+ $write=null,
+ $except=null,
+ 1)) {
+ // allow signals to be observed
+ }
+ $name = fgets(STDIN);
+
+ // Since pcntl_signal() doesn't return the old signal handler, the
+ // best we can do here is set it back to the default behavior.
+ pcntl_signal(SIGINT, SIG_DFL);
+
+ return $name;
+}
+
+// @@PLEAC@@_16.17
+function got_int($signal) {
+ pcntl_signal(SIGINT, 'got_int'); // but not for SIGCHLD!
+ // ...
+}
+pcntl_signal(SIGINT, 'got_int');
+
+// -----------------------------
+
+declare(ticks = 1);
+$interrupted = false;
+
+function got_int($signal) {
+ global $interrupted;
+ $interrupted = true;
+ // The third argument to pcntl_signal() determines if system calls
+ // should be restarted after a signal. It defaults to true.
+ pcntl_signal(SIGINT, 'got_int', false); // or SIG_IGN
+}
+pcntl_signal(SIGINT, 'got_int', false);
+
+// ... long-running code that you don't want to restart
+
+if ($interrupted) {
+ // deal with the signal
+}
+
+// @@PLEAC@@_16.18
+// ignore signal INT
+pcntl_signal(SIGINT, SIG_IGN);
+
+// install signal handler
+declare(ticks = 1);
+function tsktsk($signal) {
+ fwrite(STDERR, "\x07The long habit of living indisposeth us for dying.");
+ pcntl_signal(SIGINT, 'tsktsk');
+}
+pcntl_signal(SIGINT, 'tsktsk');
+
+// @@PLEAC@@_16.19
+pcntl_signal(SIGCHLD, SIG_IGN);
+
+// -----------------------------
+
+declare(ticks = 1);
+function reaper($signal) {
+ $pid = pcntl_waitpid(-1, $status, WNOHANG);
+ if ($pid > 0) {
+ // ...
+ reaper($signal);
+ }
+ // install *after* calling waitpid
+ pcntl_signal(SIGCHLD, 'reaper');
+}
+pcntl_signal(SIGCHLD, 'reaper');
+
+// -----------------------------
+
+declare(ticks = 1);
+function reaper($signal) {
+ $pid = pcntl_waitpid(-1, $status, WNOHANG);
+ if ($pid == -1) {
+ // No child waiting. Ignore it.
+ } else {
+ if (pcntl_wifexited($signal)) {
+ echo "Process $pid exited.\n";
+ } else {
+ echo "False alarm on $pid\n";
+ }
+ reaper($signal);
+ }
+ pcntl_signal(SIGCHLD, 'reaper');
+}
+pcntl_signal(SIGCHLD, 'reaper');
+
+// @@PLEAC@@_16.20
+// PHP does not support sigprocmask().
+
+// @@PLEAC@@_16.21
+declare(ticks = 1);
+$aborted = false;
+
+function handle_alarm($signal) {
+ global $aborted;
+ $aborted = true;
+}
+pcntl_signal(SIGALRM, 'handle_alarm');
+
+pcntl_alarm(3600);
+// long-time operations here
+pcntl_alarm(0);
+if ($aborted) {
+ // timed out - do what you will here
+}
diff --git a/test/scanners/php/suite.rb b/test/scanners/php/suite.rb
new file mode 100644
index 0000000..8d72ce3
--- /dev/null
+++ b/test/scanners/php/suite.rb
@@ -0,0 +1,2 @@
+class PHP < CodeRay::TestCase
+end
diff --git a/test/scanners/php/test.expected.raydebug b/test/scanners/php/test.expected.raydebug
new file mode 100644
index 0000000..30c860c
--- /dev/null
+++ b/test/scanners/php/test.expected.raydebug
@@ -0,0 +1,498 @@
+operator(<)operator(?)ident(php)
+comment(/*)comment(*)
+comment( * Zip class file)
+comment( *)
+comment( * @package fnord.bb)
+comment( * @subpackage archive)
+comment( )comment(*/)
+
+comment(// Unlock?)
+reserved(if)operator(()operator(!)ident(defined)operator(()delimiter(')string(UNLOCK)delimiter(')operator(\)) operator(|)operator(|) operator(!)constant(UNLOCK)operator(\))
+ reserved(die)operator(()operator(\))operator(;)
+
+comment(// Load the parent archive class)
+pre_type(require_once)operator(()constant(ROOT_PATH)operator(.)delimiter(')string(/classes/archive.class.php)delimiter(')operator(\))operator(;)
+
+comment(/*)comment(*)
+comment( * Zip class)
+comment( *)
+comment( * @author Manni <manni@fnord.name>)
+comment( * @copyright Copyright (c\) 2006, Manni)
+comment( * @version 1.0)
+comment( * @link http://www.pkware.com/business_and_developers/developer/popups/appnote.txt)
+comment( * @link http://mannithedark.is-a-geek.net/)
+comment( * @since 1.0)
+comment( * @package fnord.bb)
+comment( * @subpackage archive)
+comment( )comment(*/)
+pre_type(class) constant(Zip) pre_type(extends) constant(Archive) operator({)
+ comment(/*)comment(*)
+comment( * Outputs the zip file)
+comment( *)
+comment( * This function creates the zip file with the dirs and files given.)
+comment( * If the optional parameter $file is given, the zip file is will be)
+comment( * saved at that location. Otherwise the function returns the zip file's content.)
+comment( *)
+comment( * @access public)
+comment( *)
+comment( * @link http://www.pkware.com/business_and_developers/developer/popups/appnote.txt)
+comment( * @param string $filename The path where the zip file will be saved)
+comment( *)
+comment( * @return bool|string Returns either true if the fil is sucessfully created or the content of the zip file)
+comment( )comment(*/)
+ pre_type(function) ident(out)operator(()local_variable($filename) operator(=) pre_type(false)operator(\)) operator({)
+ comment(// Empty output)
+ local_variable($file_data) operator(=) pre_type(array)operator(()operator(\))operator(;) comment(// Data of the file part)
+ local_variable($cd_data) operator(=) pre_type(array)operator(()operator(\))operator(;) comment(// Data of the central directory)
+
+ comment(// Sort dirs and files by path length)
+ ident(uksort)operator(()local_variable($this)operator(->)ident(dirs)operator(,) delimiter(')string(sort_by_length)delimiter(')operator(\))operator(;)
+ ident(uksort)operator(()local_variable($this)operator(->)ident(files)operator(,) delimiter(')string(sort_by_length)delimiter(')operator(\))operator(;)
+
+ comment(// Handle dirs)
+ reserved(foreach)operator(()local_variable($this)operator(->)ident(dirs) reserved(as) local_variable($dir)operator(\)) operator({)
+ local_variable($dir) operator(.)operator(=) delimiter(')string(/)delimiter(')operator(;)
+ comment(// File part)
+
+ comment(// Reset dir data)
+ local_variable($dir_data) operator(=) delimiter(')delimiter(')operator(;)
+
+ comment(// Local file header)
+ local_variable($dir_data) operator(.)operator(=) delimiter(")string(\\)string(x50)string(\\)string(x4b)string(\\)string(x03)string(\\)string(x04)delimiter(")operator(;) comment(// Local file header signature)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(10)operator(\))operator(;) comment(// Version needed to extract)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// General purpose bit flag)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Compression method)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Last mod file time)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Last mod file date)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// crc-32)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Compressed size)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Uncompressed size)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) ident(strlen)operator(()local_variable($dir)operator(\))operator(\))operator(;) comment(// File name length)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Extra field length)
+
+ local_variable($dir_data) operator(.)operator(=) local_variable($dir)operator(;) comment(// File name)
+ local_variable($dir_data) operator(.)operator(=) delimiter(')delimiter(')operator(;) comment(// Extra field (is empty\))
+
+ comment(// File data)
+ local_variable($dir_data) operator(.)operator(=) delimiter(')delimiter(')operator(;) comment(// Dirs have no file data)
+
+ comment(// Data descriptor)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// crc-32)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Compressed size)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Uncompressed size)
+
+ comment(// Save current offset)
+ local_variable($offset) operator(=) ident(strlen)operator(()ident(implode)operator(()delimiter(')delimiter(')operator(,) local_variable($file_data)operator(\))operator(\))operator(;)
+
+ comment(// Append dir data to the file part)
+ local_variable($file_data)operator([)operator(]) operator(=) local_variable($dir_data)operator(;)
+
+ comment(// Central directory)
+
+ comment(// Reset dir data)
+ local_variable($dir_data) operator(=) delimiter(')delimiter(')operator(;)
+
+ comment(// File header)
+ local_variable($dir_data) operator(.)operator(=) delimiter(")string(\\)string(x50)string(\\)string(x4b)string(\\)string(x01)string(\\)string(x02)delimiter(")operator(;) comment(// Local file header signature)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Version made by)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(10)operator(\))operator(;) comment(// Version needed to extract)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// General purpose bit flag)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Compression method)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Last mod file time)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Last mod file date)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// crc-32)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Compressed size)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Uncompressed size)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) ident(strlen)operator(()local_variable($dir)operator(\))operator(\))operator(;) comment(// File name length)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Extra field length)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// File comment length)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Disk number start)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Internal file attributes)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) integer(16)operator(\))operator(;) comment(// External file attributes)
+ local_variable($dir_data) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) local_variable($offset)operator(\))operator(;) comment(// Relative offset of local header)
+
+ local_variable($dir_data) operator(.)operator(=) local_variable($dir)operator(;) comment(// File name)
+ local_variable($dir_data) operator(.)operator(=) delimiter(')delimiter(')operator(;) comment(// Extra field (is empty\))
+ local_variable($dir_data) operator(.)operator(=) delimiter(')delimiter(')operator(;) comment(// File comment (is empty\))
+
+ comment(/*)
+comment( // Data descriptor)
+comment( $dir_data .= pack("V", 0\); // crc-32)
+comment( $dir_data .= pack("V", 0\); // Compressed size)
+comment( $dir_data .= pack("V", 0\); // Uncompressed size)
+comment( )comment(*/)
+
+ comment(// Append dir data to the central directory data)
+ local_variable($cd_data)operator([)operator(]) operator(=) local_variable($dir_data)operator(;)
+ operator(})
+
+ comment(// Handle files)
+ reserved(foreach)operator(()local_variable($this)operator(->)ident(files) reserved(as) local_variable($name) operator(=>) local_variable($file)operator(\)) operator({)
+ comment(// Get values)
+ local_variable($content) operator(=) local_variable($file)operator([)integer(0)operator(])operator(;)
+
+ comment(// File part)
+
+ comment(// Reset file data)
+ local_variable($fd) operator(=) delimiter(')delimiter(')operator(;)
+
+ comment(// Detect possible compressions)
+ comment(// Use deflate)
+ reserved(if)operator(()ident(function_exists)operator(()delimiter(')string(gzdeflate)delimiter(')operator(\))operator(\)) operator({)
+ local_variable($method) operator(=) integer(8)operator(;)
+
+ comment(// Compress file content)
+ local_variable($compressed_data) operator(=) ident(gzdeflate)operator(()local_variable($content)operator(\))operator(;)
+
+ comment(// Use bzip2)
+ operator(}) reserved(elseif)operator(()ident(function_exists)operator(()delimiter(')string(bzcompress)delimiter(')operator(\))operator(\)) operator({)
+ local_variable($method) operator(=) integer(12)operator(;)
+
+ comment(// Compress file content)
+ local_variable($compressed_data) operator(=) ident(bzcompress)operator(()local_variable($content)operator(\))operator(;)
+
+ comment(// No compression)
+ operator(}) reserved(else) operator({)
+ local_variable($method) operator(=) integer(0)operator(;)
+
+ comment(// Do not compress the content :P)
+ local_variable($compressed_data) operator(=) local_variable($content)operator(;)
+ operator(})
+
+ comment(// Local file header)
+ local_variable($fd) operator(.)operator(=) delimiter(")string(\\)string(x50)string(\\)string(x4b)string(\\)string(x03)string(\\)string(x04)delimiter(")operator(;) comment(// Local file header signature)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(20)operator(\))operator(;) comment(// Version needed to extract)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// General purpose bit flag)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) local_variable($method)operator(\))operator(;) comment(// Compression method)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Last mod file time)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Last mod file date)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) ident(crc32)operator(()local_variable($content)operator(\))operator(\))operator(;) comment(// crc-32)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) ident(strlen)operator(()local_variable($compressed_data)operator(\))operator(\))operator(;) comment(// Compressed size)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) ident(strlen)operator(()local_variable($content)operator(\))operator(\))operator(;) comment(// Uncompressed size)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) ident(strlen)operator(()local_variable($name)operator(\))operator(\))operator(;) comment(// File name length)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Extra field length)
+
+ local_variable($fd) operator(.)operator(=) local_variable($name)operator(;) comment(// File name)
+ local_variable($fd) operator(.)operator(=) delimiter(')delimiter(')operator(;) comment(// Extra field (is empty\))
+
+ comment(// File data)
+ local_variable($fd) operator(.)operator(=) local_variable($compressed_data)operator(;)
+
+ comment(// Data descriptor)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) ident(crc32)operator(()local_variable($content)operator(\))operator(\))operator(;) comment(// crc-32)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) ident(strlen)operator(()local_variable($compressed_data)operator(\))operator(\))operator(;) comment(// Compressed size)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) ident(strlen)operator(()local_variable($content)operator(\))operator(\))operator(;) comment(// Uncompressed size)
+
+ comment(// Save current offset)
+ local_variable($offset) operator(=) ident(strlen)operator(()ident(implode)operator(()delimiter(')delimiter(')operator(,) local_variable($file_data)operator(\))operator(\))operator(;)
+
+ comment(// Append file data to the file part)
+ local_variable($file_data)operator([)operator(]) operator(=) local_variable($fd)operator(;)
+
+ comment(// Central directory)
+
+ comment(// Reset file data)
+ local_variable($fd) operator(=) delimiter(')delimiter(')operator(;)
+
+ comment(// File header)
+ local_variable($fd) operator(.)operator(=) delimiter(")string(\\)string(x50)string(\\)string(x4b)string(\\)string(x01)string(\\)string(x02)delimiter(")operator(;) comment(// Local file header signature)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Version made by)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(20)operator(\))operator(;) comment(// Version needed to extract)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// General purpose bit flag)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) local_variable($method)operator(\))operator(;) comment(// Compression method)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Last mod file time)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Last mod file date)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) ident(crc32)operator(()local_variable($content)operator(\))operator(\))operator(;) comment(// crc-32)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) ident(strlen)operator(()local_variable($compressed_data)operator(\))operator(\))operator(;) comment(// Compressed size)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) ident(strlen)operator(()local_variable($content)operator(\))operator(\))operator(;) comment(// Uncompressed size)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) ident(strlen)operator(()local_variable($name)operator(\))operator(\))operator(;) comment(// File name length)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Extra field length)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// File comment length)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Disk number start)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Internal file attributes)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) integer(32)operator(\))operator(;) comment(// External file attributes)
+ local_variable($fd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) local_variable($offset)operator(\))operator(;) comment(// Relative offset of local header)
+
+ local_variable($fd) operator(.)operator(=) local_variable($name)operator(;) comment(// File name)
+ local_variable($fd) operator(.)operator(=) delimiter(')delimiter(')operator(;) comment(// Extra field (is empty\))
+ local_variable($fd) operator(.)operator(=) delimiter(')delimiter(')operator(;) comment(// File comment (is empty\))
+
+ comment(/*)
+comment( // Data descriptor)
+comment( $fd .= pack("V", crc32($content\)\); // crc-32)
+comment( $fd .= pack("V", strlen($compressed_data\)\); // Compressed size)
+comment( $fd .= pack("V", strlen($content\)\); // Uncompressed size)
+comment( )comment(*/)
+
+ comment(// Append file data to the central directory data)
+ local_variable($cd_data)operator([)operator(]) operator(=) local_variable($fd)operator(;)
+ operator(})
+
+ comment(// Digital signature)
+ local_variable($digital_signature) operator(=) delimiter(')delimiter(')operator(;)
+ local_variable($digital_signature) operator(.)operator(=) delimiter(")string(\\)string(x50)string(\\)string(x4b)string(\\)string(x05)string(\\)string(x05)delimiter(")operator(;) comment(// Header signature)
+ local_variable($digital_signature) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Size of data)
+ local_variable($digital_signature) operator(.)operator(=) delimiter(')delimiter(')operator(;) comment(// Signature data (is empty\))
+
+ local_variable($tmp_file_data) operator(=) ident(implode)operator(()delimiter(')delimiter(')operator(,) local_variable($file_data)operator(\))operator(;) comment(// File data)
+ local_variable($tmp_cd_data) operator(=) ident(implode)operator(()delimiter(')delimiter(')operator(,) local_variable($cd_data)operator(\))operator(.) comment(// Central directory)
+ local_variable($digital_signature)operator(;) comment(// Digital signature)
+
+ comment(// End of central directory)
+ local_variable($eof_cd) operator(=) delimiter(')delimiter(')operator(;)
+ local_variable($eof_cd) operator(.)operator(=) delimiter(")string(\\)string(x50)string(\\)string(x4b)string(\\)string(x05)string(\\)string(x06)delimiter(")operator(;) comment(// End of central dir signature)
+ local_variable($eof_cd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Number of this disk)
+ local_variable($eof_cd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// Number of the disk with the start of the central directory)
+ local_variable($eof_cd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) ident(count)operator(()local_variable($cd_data)operator(\))operator(\))operator(;) comment(// Total number of entries in the central directory on this disk)
+ local_variable($eof_cd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) ident(count)operator(()local_variable($cd_data)operator(\))operator(\))operator(;) comment(// Total number of entries in the central directory)
+ local_variable($eof_cd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) ident(strlen)operator(()local_variable($tmp_cd_data)operator(\))operator(\))operator(;) comment(// Size of the central directory)
+ local_variable($eof_cd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(V)delimiter(")operator(,) ident(strlen)operator(()local_variable($tmp_file_data)operator(\))operator(\))operator(;) comment(// Offset of start of central directory with respect to the starting disk number)
+ local_variable($eof_cd) operator(.)operator(=) ident(pack)operator(()delimiter(")string(v)delimiter(")operator(,) integer(0)operator(\))operator(;) comment(// .ZIP file comment length)
+ local_variable($eof_cd) operator(.)operator(=) delimiter(')delimiter(')operator(;) comment(// .ZIP file comment (is empty\))
+
+ comment(// Content of the zip file)
+ local_variable($data) operator(=) local_variable($tmp_file_data)operator(.)
+ comment(// $extra_data_record.)
+ local_variable($tmp_cd_data)operator(.)
+ local_variable($eof_cd)operator(;)
+
+ comment(// Return content?)
+ reserved(if)operator(()operator(!)local_variable($filename)operator(\))
+ reserved(return) local_variable($data)operator(;)
+
+ comment(// Write to file)
+ reserved(return) ident(file_put_contents)operator(()local_variable($filename)operator(,) local_variable($data)operator(\))operator(;)
+ operator(})
+
+ comment(/*)comment(*)
+comment( * Load a zip file)
+comment( *)
+comment( * This function loads the files and dirs from a zip file from the harddrive.)
+comment( *)
+comment( * @access public)
+comment( *)
+comment( * @param string $file The path to the zip file)
+comment( * @param bool $reset Reset the files and dirs before adding the zip file's content?)
+comment( *)
+comment( * @return bool Returns true if the file was loaded sucessfully)
+comment( )comment(*/)
+ pre_type(function) ident(load_file)operator(()local_variable($file)operator(,) local_variable($reset) operator(=) pre_type(true)operator(\)) operator({)
+ comment(// Check whether the file exists)
+ reserved(if)operator(()operator(!)ident(file_exists)operator(()local_variable($file)operator(\))operator(\))
+ reserved(return) pre_type(false)operator(;)
+
+ comment(// Load the files content)
+ local_variable($content) operator(=) operator(@)ident(file_get_contents)operator(()local_variable($file)operator(\))operator(;)
+
+ comment(// Return false if the file cannot be opened)
+ reserved(if)operator(()operator(!)local_variable($content)operator(\))
+ reserved(return) pre_type(false)operator(;)
+
+ comment(// Read the zip)
+ reserved(return) local_variable($this)operator(->)ident(load_string)operator(()local_variable($content)operator(,) local_variable($reset)operator(\))operator(;)
+ operator(})
+
+ comment(/*)comment(*)
+comment( * Load a zip string)
+comment( *)
+comment( * This function loads the files and dirs from a string)
+comment( *)
+comment( * @access public)
+comment( *)
+comment( * @param string $string The string the zip is generated from)
+comment( * @param bool $reset Reset the files and dirs before adding the zip file's content?)
+comment( *)
+comment( * @return bool Returns true if the string was loaded sucessfully)
+comment( )comment(*/)
+ pre_type(function) ident(load_string)operator(()local_variable($string)operator(,) local_variable($reset) operator(=) pre_type(true)operator(\)) operator({)
+ comment(// Reset the zip?)
+ reserved(if)operator(()local_variable($reset)operator(\)) operator({)
+ local_variable($this)operator(->)ident(dirs) operator(=) pre_type(array)operator(()operator(\))operator(;)
+ local_variable($this)operator(->)ident(files) operator(=) pre_type(array)operator(()operator(\))operator(;)
+ operator(})
+
+ comment(// Get the starting position of the end of central directory record)
+ local_variable($start) operator(=) ident(strpos)operator(()local_variable($string)operator(,) delimiter(")string(\\)string(x50)string(\\)string(x4b)string(\\)string(x05)string(\\)string(x06)delimiter(")operator(\))operator(;)
+
+ comment(// Error)
+ reserved(if)operator(()local_variable($start) operator(===) pre_type(false)operator(\))
+ reserved(die)operator(()delimiter(')string(Could not find the end of central directory record)delimiter(')operator(\))operator(;)
+
+ comment(// Get the ecdr)
+ local_variable($eof_cd) operator(=) ident(substr)operator(()local_variable($string)operator(,) local_variable($start)operator(+)integer(4)operator(,) integer(18)operator(\))operator(;)
+
+ comment(// Unpack the ecdr infos)
+ local_variable($eof_cd) operator(=) ident(unpack)operator(()delimiter(')string(vdisc1/)delimiter(')operator(.)
+ delimiter(')string(vdisc2/)delimiter(')operator(.)
+ delimiter(')string(ventries1/)delimiter(')operator(.)
+ delimiter(')string(ventries2/)delimiter(')operator(.)
+ delimiter(')string(Vsize/)delimiter(')operator(.)
+ delimiter(')string(Voffset/)delimiter(')operator(.)
+ delimiter(')string(vcomment_lenght)delimiter(')operator(,) local_variable($eof_cd)operator(\))operator(;)
+
+ comment(// Do not allow multi disc zips)
+ reserved(if)operator(()local_variable($eof_cd)operator([)delimiter(')string(disc1)delimiter(')operator(]) operator(!=) integer(0)operator(\))
+ reserved(die)operator(()delimiter(')string(multi disk stuff is not yet implemented :/)delimiter(')operator(\))operator(;)
+
+ comment(// Save the interesting values)
+ local_variable($cd_entries) operator(=) local_variable($eof_cd)operator([)delimiter(')string(entries1)delimiter(')operator(])operator(;)
+ local_variable($cd_size) operator(=) local_variable($eof_cd)operator([)delimiter(')string(size)delimiter(')operator(])operator(;)
+ local_variable($cd_offset) operator(=) local_variable($eof_cd)operator([)delimiter(')string(offset)delimiter(')operator(])operator(;)
+
+ comment(// Get the central directory record)
+ local_variable($cdr) operator(=) ident(substr)operator(()local_variable($string)operator(,) local_variable($cd_offset)operator(,) local_variable($cd_size)operator(\))operator(;)
+
+ comment(// Reset the position and the list of the entries)
+ local_variable($pos) operator(=) integer(0)operator(;)
+ local_variable($entries) operator(=) pre_type(array)operator(()operator(\))operator(;)
+
+ comment(// Handle cdr)
+ reserved(while)operator(()local_variable($pos) operator(<) ident(strlen)operator(()local_variable($cdr)operator(\))operator(\)) operator({)
+ comment(// Check header signature)
+ comment(// Digital signature)
+ reserved(if)operator(()ident(substr)operator(()local_variable($cdr)operator(,) local_variable($pos)operator(,) integer(4)operator(\)) operator(==) delimiter(")string(\\)string(x50)string(\\)string(x4b)string(\\)string(x05)string(\\)string(x05)delimiter(")operator(\)) operator({)
+ comment(// Get digital signature size)
+ local_variable($tmp_info) operator(=) ident(unpack)operator(()delimiter(')string(vsize)delimiter(')operator(,) ident(substr)operator(()local_variable($cdr)operator(,) local_variable($pos) operator(+) integer(4)operator(,) integer(2)operator(\))operator(\))operator(;)
+
+ comment(// Read out the digital signature)
+ local_variable($digital_sig) operator(=) ident(substr)operator(()local_variable($header)operator(,) local_variable($pos) operator(+) integer(6)operator(,) local_variable($tmp_info)operator([)delimiter(')string(size)delimiter(')operator(])operator(\))operator(;)
+
+ reserved(break)operator(;)
+ operator(})
+
+ comment(// Get file header)
+ local_variable($header) operator(=) ident(substr)operator(()local_variable($cdr)operator(,) local_variable($pos)operator(,) integer(46)operator(\))operator(;)
+
+ comment(// Unpack the header information)
+ local_variable($header_info) operator(=) operator(@)ident(unpack)operator(()delimiter(')string(Vheader/)delimiter(')operator(.)
+ delimiter(')string(vversion_made_by/)delimiter(')operator(.)
+ delimiter(')string(vversion_needed/)delimiter(')operator(.)
+ delimiter(')string(vgeneral_purpose/)delimiter(')operator(.)
+ delimiter(')string(vcompression_method/)delimiter(')operator(.)
+ delimiter(')string(vlast_mod_time/)delimiter(')operator(.)
+ delimiter(')string(vlast_mod_date/)delimiter(')operator(.)
+ delimiter(')string(Vcrc32/)delimiter(')operator(.)
+ delimiter(')string(Vcompressed_size/)delimiter(')operator(.)
+ delimiter(')string(Vuncompressed_size/)delimiter(')operator(.)
+ delimiter(')string(vname_length/)delimiter(')operator(.)
+ delimiter(')string(vextra_length/)delimiter(')operator(.)
+ delimiter(')string(vcomment_length/)delimiter(')operator(.)
+ delimiter(')string(vdisk_number/)delimiter(')operator(.)
+ delimiter(')string(vinternal_attributes/)delimiter(')operator(.)
+ delimiter(')string(Vexternal_attributes/)delimiter(')operator(.)
+ delimiter(')string(Voffset)delimiter(')operator(,)
+ local_variable($header)operator(\))operator(;)
+
+ comment(// Valid header?)
+ reserved(if)operator(()local_variable($header_info)operator([)delimiter(')string(header)delimiter(')operator(]) operator(!=) integer(33639248)operator(\))
+ reserved(return) pre_type(false)operator(;)
+
+ comment(// New position)
+ local_variable($pos) operator(+)operator(=) integer(46)operator(;)
+
+ comment(// Read out the file name)
+ local_variable($header_info)operator([)delimiter(')string(name)delimiter(')operator(]) operator(=) ident(substr)operator(()local_variable($cdr)operator(,) local_variable($pos)operator(,) local_variable($header_info)operator([)delimiter(')string(name_length)delimiter(')operator(])operator(\))operator(;)
+
+ comment(// New position)
+ local_variable($pos) operator(+)operator(=) local_variable($header_info)operator([)delimiter(')string(name_length)delimiter(')operator(])operator(;)
+
+ comment(// Read out the extra stuff)
+ local_variable($header_info)operator([)delimiter(')string(extra)delimiter(')operator(]) operator(=) ident(substr)operator(()local_variable($cdr)operator(,) local_variable($pos)operator(,) local_variable($header_info)operator([)delimiter(')string(extra_length)delimiter(')operator(])operator(\))operator(;)
+
+ comment(// New position)
+ local_variable($pos) operator(+)operator(=) local_variable($header_info)operator([)delimiter(')string(extra_length)delimiter(')operator(])operator(;)
+
+ comment(// Read out the comment)
+ local_variable($header_info)operator([)delimiter(')string(comment)delimiter(')operator(]) operator(=) ident(substr)operator(()local_variable($cdr)operator(,) local_variable($pos)operator(,) local_variable($header_info)operator([)delimiter(')string(comment_length)delimiter(')operator(])operator(\))operator(;)
+
+ comment(// New position)
+ local_variable($pos) operator(+)operator(=) local_variable($header_info)operator([)delimiter(')string(comment_length)delimiter(')operator(])operator(;)
+
+ comment(// Append this file/dir to the entry list)
+ local_variable($entries)operator([)operator(]) operator(=) local_variable($header_info)operator(;)
+ operator(})
+
+ comment(// Check whether all entries where read sucessfully)
+ reserved(if)operator(()ident(count)operator(()local_variable($entries)operator(\)) operator(!=) local_variable($cd_entries)operator(\))
+ reserved(return) pre_type(false)operator(;)
+
+ comment(// Handle files/dirs)
+ reserved(foreach)operator(()local_variable($entries) reserved(as) local_variable($entry)operator(\)) operator({)
+ comment(// Is a dir?)
+ reserved(if)operator(()local_variable($entry)operator([)delimiter(')string(external_attributes)delimiter(')operator(]) operator(&) integer(16)operator(\)) operator({)
+ local_variable($this)operator(->)ident(add_dir)operator(()local_variable($entry)operator([)delimiter(')string(name)delimiter(')operator(])operator(\))operator(;)
+ reserved(continue)operator(;)
+ operator(})
+
+ comment(// Get local file header)
+ local_variable($header) operator(=) ident(substr)operator(()local_variable($string)operator(,) local_variable($entry)operator([)delimiter(')string(offset)delimiter(')operator(])operator(,) integer(30)operator(\))operator(;)
+
+ comment(// Unpack the header information)
+ local_variable($header_info) operator(=) operator(@)ident(unpack)operator(()delimiter(')string(Vheader/)delimiter(')operator(.)
+ delimiter(')string(vversion_needed/)delimiter(')operator(.)
+ delimiter(')string(vgeneral_purpose/)delimiter(')operator(.)
+ delimiter(')string(vcompression_method/)delimiter(')operator(.)
+ delimiter(')string(vlast_mod_time/)delimiter(')operator(.)
+ delimiter(')string(vlast_mod_date/)delimiter(')operator(.)
+ delimiter(')string(Vcrc32/)delimiter(')operator(.)
+ delimiter(')string(Vcompressed_size/)delimiter(')operator(.)
+ delimiter(')string(Vuncompressed_size/)delimiter(')operator(.)
+ delimiter(')string(vname_length/)delimiter(')operator(.)
+ delimiter(')string(vextra_length)delimiter(')operator(,)
+ local_variable($header)operator(\))operator(;)
+
+ comment(// Valid header?)
+ reserved(if)operator(()local_variable($header_info)operator([)delimiter(')string(header)delimiter(')operator(]) operator(!=) integer(67324752)operator(\))
+ reserved(return) pre_type(false)operator(;)
+
+ comment(// Get content start position)
+ local_variable($start) operator(=) local_variable($entry)operator([)delimiter(')string(offset)delimiter(')operator(]) operator(+) integer(30) operator(+) local_variable($header_info)operator([)delimiter(')string(name_length)delimiter(')operator(]) operator(+) local_variable($header_info)operator([)delimiter(')string(extra_length)delimiter(')operator(])operator(;)
+
+ comment(// Get the compressed data)
+ local_variable($data) operator(=) ident(substr)operator(()local_variable($string)operator(,) local_variable($start)operator(,) local_variable($header_info)operator([)delimiter(')string(compressed_size)delimiter(')operator(])operator(\))operator(;)
+
+ comment(// Detect compression type)
+ reserved(switch)operator(()local_variable($header_info)operator([)delimiter(')string(compression_method)delimiter(')operator(])operator(\)) operator({)
+ comment(// No compression)
+ reserved(case) integer(0)operator(:)
+ comment(// Ne decompression needed)
+ local_variable($content) operator(=) local_variable($data)operator(;)
+ reserved(break)operator(;)
+
+ comment(// Gzip)
+ reserved(case) integer(8)operator(:)
+ reserved(if)operator(()operator(!)ident(function_exists)operator(()delimiter(')string(gzinflate)delimiter(')operator(\))operator(\))
+ reserved(return) pre_type(false)operator(;)
+
+ comment(// Uncompress data)
+ local_variable($content) operator(=) ident(gzinflate)operator(()local_variable($data)operator(\))operator(;)
+ reserved(break)operator(;)
+
+ comment(// Bzip2)
+ reserved(case) integer(12)operator(:)
+ reserved(if)operator(()operator(!)ident(function_exists)operator(()delimiter(')string(bzdecompress)delimiter(')operator(\))operator(\))
+ reserved(return) pre_type(false)operator(;)
+
+ comment(// Decompress data)
+ local_variable($content) operator(=) ident(bzdecompress)operator(()local_variable($data)operator(\))operator(;)
+ reserved(break)operator(;)
+
+ comment(// Compression not supported -> error)
+ reserved(default)operator(:)
+ reserved(return) pre_type(false)operator(;)
+ operator(})
+
+ comment(// Try to add file)
+ reserved(if)operator(()operator(!)local_variable($this)operator(->)ident(add_file)operator(()local_variable($entry)operator([)delimiter(')string(name)delimiter(')operator(])operator(,) local_variable($content)operator(\))operator(\))
+ reserved(return) pre_type(false)operator(;)
+ operator(})
+
+ reserved(return) pre_type(true)operator(;)
+ operator(})
+operator(})
+
+pre_type(function) operator(&)ident(byref)operator(()operator(\)) operator({)
+ local_variable($x) operator(=) pre_type(array)operator(()operator(\))operator(;)
+ reserved(return) local_variable($x)operator(;)
+operator(})
+delimiter(?>)
diff --git a/test/scanners/php/test.in.php b/test/scanners/php/test.in.php
new file mode 100644
index 0000000..90de747
--- /dev/null
+++ b/test/scanners/php/test.in.php
@@ -0,0 +1,498 @@
+<?php
+/**
+ * Zip class file
+ *
+ * @package fnord.bb
+ * @subpackage archive
+ */
+
+// Unlock?
+if(!defined('UNLOCK') || !UNLOCK)
+ die();
+
+// Load the parent archive class
+require_once(ROOT_PATH.'/classes/archive.class.php');
+
+/**
+ * Zip class
+ *
+ * @author Manni <manni@fnord.name>
+ * @copyright Copyright (c) 2006, Manni
+ * @version 1.0
+ * @link http://www.pkware.com/business_and_developers/developer/popups/appnote.txt
+ * @link http://mannithedark.is-a-geek.net/
+ * @since 1.0
+ * @package fnord.bb
+ * @subpackage archive
+ */
+class Zip extends Archive {
+ /**
+ * Outputs the zip file
+ *
+ * This function creates the zip file with the dirs and files given.
+ * If the optional parameter $file is given, the zip file is will be
+ * saved at that location. Otherwise the function returns the zip file's content.
+ *
+ * @access public
+ *
+ * @link http://www.pkware.com/business_and_developers/developer/popups/appnote.txt
+ * @param string $filename The path where the zip file will be saved
+ *
+ * @return bool|string Returns either true if the fil is sucessfully created or the content of the zip file
+ */
+ function out($filename = false) {
+ // Empty output
+ $file_data = array(); // Data of the file part
+ $cd_data = array(); // Data of the central directory
+
+ // Sort dirs and files by path length
+ uksort($this->dirs, 'sort_by_length');
+ uksort($this->files, 'sort_by_length');
+
+ // Handle dirs
+ foreach($this->dirs as $dir) {
+ $dir .= '/';
+ // File part
+
+ // Reset dir data
+ $dir_data = '';
+
+ // Local file header
+ $dir_data .= "\x50\x4b\x03\x04"; // Local file header signature
+ $dir_data .= pack("v", 10); // Version needed to extract
+ $dir_data .= pack("v", 0); // General purpose bit flag
+ $dir_data .= pack("v", 0); // Compression method
+ $dir_data .= pack("v", 0); // Last mod file time
+ $dir_data .= pack("v", 0); // Last mod file date
+ $dir_data .= pack("V", 0); // crc-32
+ $dir_data .= pack("V", 0); // Compressed size
+ $dir_data .= pack("V", 0); // Uncompressed size
+ $dir_data .= pack("v", strlen($dir)); // File name length
+ $dir_data .= pack("v", 0); // Extra field length
+
+ $dir_data .= $dir; // File name
+ $dir_data .= ''; // Extra field (is empty)
+
+ // File data
+ $dir_data .= ''; // Dirs have no file data
+
+ // Data descriptor
+ $dir_data .= pack("V", 0); // crc-32
+ $dir_data .= pack("V", 0); // Compressed size
+ $dir_data .= pack("V", 0); // Uncompressed size
+
+ // Save current offset
+ $offset = strlen(implode('', $file_data));
+
+ // Append dir data to the file part
+ $file_data[] = $dir_data;
+
+ // Central directory
+
+ // Reset dir data
+ $dir_data = '';
+
+ // File header
+ $dir_data .= "\x50\x4b\x01\x02"; // Local file header signature
+ $dir_data .= pack("v", 0); // Version made by
+ $dir_data .= pack("v", 10); // Version needed to extract
+ $dir_data .= pack("v", 0); // General purpose bit flag
+ $dir_data .= pack("v", 0); // Compression method
+ $dir_data .= pack("v", 0); // Last mod file time
+ $dir_data .= pack("v", 0); // Last mod file date
+ $dir_data .= pack("V", 0); // crc-32
+ $dir_data .= pack("V", 0); // Compressed size
+ $dir_data .= pack("V", 0); // Uncompressed size
+ $dir_data .= pack("v", strlen($dir)); // File name length
+ $dir_data .= pack("v", 0); // Extra field length
+ $dir_data .= pack("v", 0); // File comment length
+ $dir_data .= pack("v", 0); // Disk number start
+ $dir_data .= pack("v", 0); // Internal file attributes
+ $dir_data .= pack("V", 16); // External file attributes
+ $dir_data .= pack("V", $offset); // Relative offset of local header
+
+ $dir_data .= $dir; // File name
+ $dir_data .= ''; // Extra field (is empty)
+ $dir_data .= ''; // File comment (is empty)
+
+ /*
+ // Data descriptor
+ $dir_data .= pack("V", 0); // crc-32
+ $dir_data .= pack("V", 0); // Compressed size
+ $dir_data .= pack("V", 0); // Uncompressed size
+ */
+
+ // Append dir data to the central directory data
+ $cd_data[] = $dir_data;
+ }
+
+ // Handle files
+ foreach($this->files as $name => $file) {
+ // Get values
+ $content = $file[0];
+
+ // File part
+
+ // Reset file data
+ $fd = '';
+
+ // Detect possible compressions
+ // Use deflate
+ if(function_exists('gzdeflate')) {
+ $method = 8;
+
+ // Compress file content
+ $compressed_data = gzdeflate($content);
+
+ // Use bzip2
+ } elseif(function_exists('bzcompress')) {
+ $method = 12;
+
+ // Compress file content
+ $compressed_data = bzcompress($content);
+
+ // No compression
+ } else {
+ $method = 0;
+
+ // Do not compress the content :P
+ $compressed_data = $content;
+ }
+
+ // Local file header
+ $fd .= "\x50\x4b\x03\x04"; // Local file header signature
+ $fd .= pack("v", 20); // Version needed to extract
+ $fd .= pack("v", 0); // General purpose bit flag
+ $fd .= pack("v", $method); // Compression method
+ $fd .= pack("v", 0); // Last mod file time
+ $fd .= pack("v", 0); // Last mod file date
+ $fd .= pack("V", crc32($content)); // crc-32
+ $fd .= pack("V", strlen($compressed_data)); // Compressed size
+ $fd .= pack("V", strlen($content)); // Uncompressed size
+ $fd .= pack("v", strlen($name)); // File name length
+ $fd .= pack("v", 0); // Extra field length
+
+ $fd .= $name; // File name
+ $fd .= ''; // Extra field (is empty)
+
+ // File data
+ $fd .= $compressed_data;
+
+ // Data descriptor
+ $fd .= pack("V", crc32($content)); // crc-32
+ $fd .= pack("V", strlen($compressed_data)); // Compressed size
+ $fd .= pack("V", strlen($content)); // Uncompressed size
+
+ // Save current offset
+ $offset = strlen(implode('', $file_data));
+
+ // Append file data to the file part
+ $file_data[] = $fd;
+
+ // Central directory
+
+ // Reset file data
+ $fd = '';
+
+ // File header
+ $fd .= "\x50\x4b\x01\x02"; // Local file header signature
+ $fd .= pack("v", 0); // Version made by
+ $fd .= pack("v", 20); // Version needed to extract
+ $fd .= pack("v", 0); // General purpose bit flag
+ $fd .= pack("v", $method); // Compression method
+ $fd .= pack("v", 0); // Last mod file time
+ $fd .= pack("v", 0); // Last mod file date
+ $fd .= pack("V", crc32($content)); // crc-32
+ $fd .= pack("V", strlen($compressed_data)); // Compressed size
+ $fd .= pack("V", strlen($content)); // Uncompressed size
+ $fd .= pack("v", strlen($name)); // File name length
+ $fd .= pack("v", 0); // Extra field length
+ $fd .= pack("v", 0); // File comment length
+ $fd .= pack("v", 0); // Disk number start
+ $fd .= pack("v", 0); // Internal file attributes
+ $fd .= pack("V", 32); // External file attributes
+ $fd .= pack("V", $offset); // Relative offset of local header
+
+ $fd .= $name; // File name
+ $fd .= ''; // Extra field (is empty)
+ $fd .= ''; // File comment (is empty)
+
+ /*
+ // Data descriptor
+ $fd .= pack("V", crc32($content)); // crc-32
+ $fd .= pack("V", strlen($compressed_data)); // Compressed size
+ $fd .= pack("V", strlen($content)); // Uncompressed size
+ */
+
+ // Append file data to the central directory data
+ $cd_data[] = $fd;
+ }
+
+ // Digital signature
+ $digital_signature = '';
+ $digital_signature .= "\x50\x4b\x05\x05"; // Header signature
+ $digital_signature .= pack("v", 0); // Size of data
+ $digital_signature .= ''; // Signature data (is empty)
+
+ $tmp_file_data = implode('', $file_data); // File data
+ $tmp_cd_data = implode('', $cd_data). // Central directory
+ $digital_signature; // Digital signature
+
+ // End of central directory
+ $eof_cd = '';
+ $eof_cd .= "\x50\x4b\x05\x06"; // End of central dir signature
+ $eof_cd .= pack("v", 0); // Number of this disk
+ $eof_cd .= pack("v", 0); // Number of the disk with the start of the central directory
+ $eof_cd .= pack("v", count($cd_data)); // Total number of entries in the central directory on this disk
+ $eof_cd .= pack("v", count($cd_data)); // Total number of entries in the central directory
+ $eof_cd .= pack("V", strlen($tmp_cd_data)); // Size of the central directory
+ $eof_cd .= pack("V", strlen($tmp_file_data)); // Offset of start of central directory with respect to the starting disk number
+ $eof_cd .= pack("v", 0); // .ZIP file comment length
+ $eof_cd .= ''; // .ZIP file comment (is empty)
+
+ // Content of the zip file
+ $data = $tmp_file_data.
+ // $extra_data_record.
+ $tmp_cd_data.
+ $eof_cd;
+
+ // Return content?
+ if(!$filename)
+ return $data;
+
+ // Write to file
+ return file_put_contents($filename, $data);
+ }
+
+ /**
+ * Load a zip file
+ *
+ * This function loads the files and dirs from a zip file from the harddrive.
+ *
+ * @access public
+ *
+ * @param string $file The path to the zip file
+ * @param bool $reset Reset the files and dirs before adding the zip file's content?
+ *
+ * @return bool Returns true if the file was loaded sucessfully
+ */
+ function load_file($file, $reset = true) {
+ // Check whether the file exists
+ if(!file_exists($file))
+ return false;
+
+ // Load the files content
+ $content = @file_get_contents($file);
+
+ // Return false if the file cannot be opened
+ if(!$content)
+ return false;
+
+ // Read the zip
+ return $this->load_string($content, $reset);
+ }
+
+ /**
+ * Load a zip string
+ *
+ * This function loads the files and dirs from a string
+ *
+ * @access public
+ *
+ * @param string $string The string the zip is generated from
+ * @param bool $reset Reset the files and dirs before adding the zip file's content?
+ *
+ * @return bool Returns true if the string was loaded sucessfully
+ */
+ function load_string($string, $reset = true) {
+ // Reset the zip?
+ if($reset) {
+ $this->dirs = array();
+ $this->files = array();
+ }
+
+ // Get the starting position of the end of central directory record
+ $start = strpos($string, "\x50\x4b\x05\x06");
+
+ // Error
+ if($start === false)
+ die('Could not find the end of central directory record');
+
+ // Get the ecdr
+ $eof_cd = substr($string, $start+4, 18);
+
+ // Unpack the ecdr infos
+ $eof_cd = unpack('vdisc1/'.
+ 'vdisc2/'.
+ 'ventries1/'.
+ 'ventries2/'.
+ 'Vsize/'.
+ 'Voffset/'.
+ 'vcomment_lenght', $eof_cd);
+
+ // Do not allow multi disc zips
+ if($eof_cd['disc1'] != 0)
+ die('multi disk stuff is not yet implemented :/');
+
+ // Save the interesting values
+ $cd_entries = $eof_cd['entries1'];
+ $cd_size = $eof_cd['size'];
+ $cd_offset = $eof_cd['offset'];
+
+ // Get the central directory record
+ $cdr = substr($string, $cd_offset, $cd_size);
+
+ // Reset the position and the list of the entries
+ $pos = 0;
+ $entries = array();
+
+ // Handle cdr
+ while($pos < strlen($cdr)) {
+ // Check header signature
+ // Digital signature
+ if(substr($cdr, $pos, 4) == "\x50\x4b\x05\x05") {
+ // Get digital signature size
+ $tmp_info = unpack('vsize', substr($cdr, $pos + 4, 2));
+
+ // Read out the digital signature
+ $digital_sig = substr($header, $pos + 6, $tmp_info['size']);
+
+ break;
+ }
+
+ // Get file header
+ $header = substr($cdr, $pos, 46);
+
+ // Unpack the header information
+ $header_info = @unpack('Vheader/'.
+ 'vversion_made_by/'.
+ 'vversion_needed/'.
+ 'vgeneral_purpose/'.
+ 'vcompression_method/'.
+ 'vlast_mod_time/'.
+ 'vlast_mod_date/'.
+ 'Vcrc32/'.
+ 'Vcompressed_size/'.
+ 'Vuncompressed_size/'.
+ 'vname_length/'.
+ 'vextra_length/'.
+ 'vcomment_length/'.
+ 'vdisk_number/'.
+ 'vinternal_attributes/'.
+ 'Vexternal_attributes/'.
+ 'Voffset',
+ $header);
+
+ // Valid header?
+ if($header_info['header'] != 33639248)
+ return false;
+
+ // New position
+ $pos += 46;
+
+ // Read out the file name
+ $header_info['name'] = substr($cdr, $pos, $header_info['name_length']);
+
+ // New position
+ $pos += $header_info['name_length'];
+
+ // Read out the extra stuff
+ $header_info['extra'] = substr($cdr, $pos, $header_info['extra_length']);
+
+ // New position
+ $pos += $header_info['extra_length'];
+
+ // Read out the comment
+ $header_info['comment'] = substr($cdr, $pos, $header_info['comment_length']);
+
+ // New position
+ $pos += $header_info['comment_length'];
+
+ // Append this file/dir to the entry list
+ $entries[] = $header_info;
+ }
+
+ // Check whether all entries where read sucessfully
+ if(count($entries) != $cd_entries)
+ return false;
+
+ // Handle files/dirs
+ foreach($entries as $entry) {
+ // Is a dir?
+ if($entry['external_attributes'] & 16) {
+ $this->add_dir($entry['name']);
+ continue;
+ }
+
+ // Get local file header
+ $header = substr($string, $entry['offset'], 30);
+
+ // Unpack the header information
+ $header_info = @unpack('Vheader/'.
+ 'vversion_needed/'.
+ 'vgeneral_purpose/'.
+ 'vcompression_method/'.
+ 'vlast_mod_time/'.
+ 'vlast_mod_date/'.
+ 'Vcrc32/'.
+ 'Vcompressed_size/'.
+ 'Vuncompressed_size/'.
+ 'vname_length/'.
+ 'vextra_length',
+ $header);
+
+ // Valid header?
+ if($header_info['header'] != 67324752)
+ return false;
+
+ // Get content start position
+ $start = $entry['offset'] + 30 + $header_info['name_length'] + $header_info['extra_length'];
+
+ // Get the compressed data
+ $data = substr($string, $start, $header_info['compressed_size']);
+
+ // Detect compression type
+ switch($header_info['compression_method']) {
+ // No compression
+ case 0:
+ // Ne decompression needed
+ $content = $data;
+ break;
+
+ // Gzip
+ case 8:
+ if(!function_exists('gzinflate'))
+ return false;
+
+ // Uncompress data
+ $content = gzinflate($data);
+ break;
+
+ // Bzip2
+ case 12:
+ if(!function_exists('bzdecompress'))
+ return false;
+
+ // Decompress data
+ $content = bzdecompress($data);
+ break;
+
+ // Compression not supported -> error
+ default:
+ return false;
+ }
+
+ // Try to add file
+ if(!$this->add_file($entry['name'], $content))
+ return false;
+ }
+
+ return true;
+ }
+}
+
+function &byref() {
+ $x = array();
+ return $x;
+}
+?>
diff --git a/test/scanners/sql/create_tables.expected.raydebug b/test/scanners/sql/create_tables.expected.raydebug
new file mode 100644
index 0000000..567c7c9
--- /dev/null
+++ b/test/scanners/sql/create_tables.expected.raydebug
@@ -0,0 +1,94 @@
+comment(--RANDOM SQL QUERIES THAT DO NOTHING INTERESTING)
+comment(--Copyright (C\) 2009 - Keith Pitt <keith@keithpitt.com>)
+
+comment(--This program is free software: you can redistribute it and/or modify)
+comment(--it under the terms of the GNU General Public License as published by)
+comment(--the Free Software Foundation, either version 3 of the License, or)
+comment(--(at your option\) any later version.)
+
+comment(--This program is distributed in the hope that it will be useful,)
+comment(--but WITHOUT ANY WARRANTY; without even the implied warranty of)
+comment(--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the)
+comment(--GNU General Public License for more details.)
+
+comment(--You should have received a copy of the GNU General Public License)
+comment(--along with this program. If not, see <http://www.gnu.org/licenses/>.)
+
+comment(-- Comment: Drop table)
+reserved(DROP) reserved(TABLE) reserved(IF) reserved(EXISTS) string<delimiter(`)content(general_lookups)delimiter(`)>operator(;)
+
+comment(-- Create table)
+reserved(CREATE) reserved(TABLE) string<delimiter(`)content(general_lookups)delimiter(`)> operator(()
+ string<delimiter(`)content(name)delimiter(`)> pre_type(varchar)operator(()integer(255)operator(\)) directive(default) pre_constant(NULL)
+operator(\)) reserved(ENGINE)operator(=)(InnoDB) directive(DEFAULT) directive(CHARSET)operator(=)(latin1)operator(;)
+
+comment(-- Drop table again)
+reserved(DROP) reserved(TABLE) reserved(IF) reserved(EXISTS) (customer)operator(;)
+
+comment(-- Create customers)
+reserved(CREATE) reserved(TABLE) (customer) operator(()
+ (first_name) pre_type(char)operator(()integer(50)operator(\))operator(,)
+ (last_name) pre_type(char)operator(()integer(50)operator(\))operator(,)
+ (address) pre_type(char)operator(()integer(50)operator(\))operator(,)
+ (city) pre_type(char)operator(()integer(50)operator(\))operator(,)
+ (country) pre_type(char)operator(()integer(25)operator(\))operator(,)
+ (birth_date) pre_type(date)operator(,)
+ (created_at) pre_type(timestamp)operator(,) comment(-- Differnt sort of date here)
+ (updated_at) pre_type(timestamp)
+operator(\))
+
+comment(-- Create business)
+reserved(CREATE) reserved(TABLE) (business) operator(()
+ (compant_name) pre_type(char)operator(()integer(50)operator(\))operator(,)
+ (address) pre_type(char)operator(()integer(50)operator(\)) directive(default) string<delimiter(')content(Address Unknown)delimiter(')>operator(,) comment(-- Oohh, defaults..)
+ (city) pre_type(char)operator(()integer(50)operator(\)) directive(default) string<delimiter(')content(Adelaide)delimiter(')>operator(,)
+ (country) pre_type(char)operator(()integer(150)operator(\)) directive(default) string<delimiter(')content(Australia)delimiter(')>
+operator(\))
+
+comment(-- Some random table)
+
+reserved(DROP) reserved(TABLE) reserved(IF) reserved(EXISTS) (customer_statuses)operator(;)
+
+reserved(CREATE) reserved(TABLE) string<delimiter(`)content(customer_statuses)delimiter(`)> operator(()
+ comment(-- Auto incrementing IDs)
+ string<delimiter(`)content(id)delimiter(`)> pre_type(smallint)operator(()integer(6)operator(\)) pre_type(unsigned) reserved(NOT) pre_constant(NULL) directive(auto_increment)operator(,)
+ string<delimiter(`)content(customer_id)delimiter(`)> pre_type(int)operator(()integer(10)operator(\)) pre_type(unsigned) reserved(NOT) pre_constant(NULL) directive(default) string<delimiter(')content(0)delimiter(')>operator(,)
+ string<delimiter(`)content(customer_client_code)delimiter(`)> pre_type(varchar)operator(()integer(15)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(entry_date)delimiter(`)> pre_type(date) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(status_id)delimiter(`)> pre_type(smallint)operator(()integer(6)operator(\)) pre_type(unsigned) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(comments)delimiter(`)> pre_type(varchar)operator(()integer(100)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ reserved(PRIMARY) reserved(KEY) operator(()string<delimiter(`)content(id)delimiter(`)>operator(\))
+operator(\)) reserved(ENGINE)operator(=)(InnoDB) directive(DEFAULT) directive(CHARSET)operator(=)(latin1)operator(;)
+
+comment(-- Try creating an index.)
+reserved(CREATE) reserved(INDEX) (customer_status_status_id) reserved(ON) (customer_statuses) operator(()(status_id)operator(\))
+
+comment(/* Now lets try and make a really big table */)
+
+reserved(DROP) reserved(TABLE) reserved(IF) reserved(EXISTS) string<delimiter(`)content(legacy_clients)delimiter(`)>operator(;)
+reserved(CREATE) reserved(TABLE) string<delimiter(`)content(legacy_clients)delimiter(`)> operator(()
+ string<delimiter(`)content(id)delimiter(`)> pre_type(int)operator(()integer(10)operator(\)) pre_type(unsigned) reserved(NOT) pre_constant(NULL) directive(auto_increment)operator(,)
+ string<delimiter(`)content(client_code)delimiter(`)> pre_type(varchar)operator(()integer(15)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(first_name)delimiter(`)> pre_type(varchar)operator(()integer(20)operator(\)) reserved(NOT) pre_constant(NULL) directive(default) string<delimiter(')delimiter(')>operator(,)
+ string<delimiter(`)content(other_name)delimiter(`)> pre_type(varchar)operator(()integer(20)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(surname)delimiter(`)> pre_type(varchar)operator(()integer(30)operator(\)) reserved(NOT) pre_constant(NULL) directive(default) string<delimiter(')delimiter(')>operator(,)
+ string<delimiter(`)content(address)delimiter(`)> pre_type(varchar)operator(()integer(50)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(suburb)delimiter(`)> pre_type(varchar)operator(()integer(50)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(postcode)delimiter(`)> pre_type(varchar)operator(()integer(10)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(location_id)delimiter(`)> pre_type(smallint)operator(()integer(3)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(home_phone)delimiter(`)> pre_type(varchar)operator(()integer(15)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(work_phone)delimiter(`)> pre_type(varchar)operator(()integer(15)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(fax)delimiter(`)> pre_type(varchar)operator(()integer(15)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(mobile)delimiter(`)> pre_type(varchar)operator(()integer(15)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(email)delimiter(`)> pre_type(varchar)operator(()integer(50)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(date_of_birth)delimiter(`)> pre_type(date) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(business_id)delimiter(`)> pre_type(int)operator(()integer(11)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(comments)delimiter(`)> pre_type(varchar)operator(()integer(100)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(state)delimiter(`)> pre_type(char)operator(()integer(3)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(sex)delimiter(`)> pre_type(char)operator(()integer(1)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(location_temp)delimiter(`)> pre_type(varchar)operator(()integer(50)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ string<delimiter(`)content(employer_temp)delimiter(`)> pre_type(varchar)operator(()integer(50)operator(\)) directive(default) pre_constant(NULL)operator(,)
+ reserved(PRIMARY) reserved(KEY) operator(()string<delimiter(`)content(id)delimiter(`)>operator(\))
+operator(\)) reserved(ENGINE)operator(=)(InnoDB) directive(DEFAULT) directive(CHARSET)operator(=)(latin1)operator(;)
+
+
diff --git a/test/scanners/sql/create_tables.in.sql b/test/scanners/sql/create_tables.in.sql
new file mode 100644
index 0000000..1844af0
--- /dev/null
+++ b/test/scanners/sql/create_tables.in.sql
@@ -0,0 +1,94 @@
+--RANDOM SQL QUERIES THAT DO NOTHING INTERESTING
+--Copyright (C) 2009 - Keith Pitt <keith@keithpitt.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 3 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, see <http://www.gnu.org/licenses/>.
+
+-- Comment: Drop table
+DROP TABLE IF EXISTS `general_lookups`;
+
+-- Create table
+CREATE TABLE `general_lookups` (
+ `name` varchar(255) default NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+-- Drop table again
+DROP TABLE IF EXISTS customer;
+
+-- Create customers
+CREATE TABLE customer (
+ first_name char(50),
+ last_name char(50),
+ address char(50),
+ city char(50),
+ country char(25),
+ birth_date date,
+ created_at timestamp, -- Differnt sort of date here
+ updated_at timestamp
+)
+
+-- Create business
+CREATE TABLE business (
+ compant_name char(50),
+ address char(50) default 'Address Unknown', -- Oohh, defaults..
+ city char(50) default 'Adelaide',
+ country char(150) default 'Australia'
+)
+
+-- Some random table
+
+DROP TABLE IF EXISTS customer_statuses;
+
+CREATE TABLE `customer_statuses` (
+ -- Auto incrementing IDs
+ `id` smallint(6) unsigned NOT NULL auto_increment,
+ `customer_id` int(10) unsigned NOT NULL default '0',
+ `customer_client_code` varchar(15) default NULL,
+ `entry_date` date default NULL,
+ `status_id` smallint(6) unsigned default NULL,
+ `comments` varchar(100) default NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+-- Try creating an index.
+CREATE INDEX customer_status_status_id ON customer_statuses (status_id)
+
+/* Now lets try and make a really big table */
+
+DROP TABLE IF EXISTS `legacy_clients`;
+CREATE TABLE `legacy_clients` (
+ `id` int(10) unsigned NOT NULL auto_increment,
+ `client_code` varchar(15) default NULL,
+ `first_name` varchar(20) NOT NULL default '',
+ `other_name` varchar(20) default NULL,
+ `surname` varchar(30) NOT NULL default '',
+ `address` varchar(50) default NULL,
+ `suburb` varchar(50) default NULL,
+ `postcode` varchar(10) default NULL,
+ `location_id` smallint(3) default NULL,
+ `home_phone` varchar(15) default NULL,
+ `work_phone` varchar(15) default NULL,
+ `fax` varchar(15) default NULL,
+ `mobile` varchar(15) default NULL,
+ `email` varchar(50) default NULL,
+ `date_of_birth` date default NULL,
+ `business_id` int(11) default NULL,
+ `comments` varchar(100) default NULL,
+ `state` char(3) default NULL,
+ `sex` char(1) default NULL,
+ `location_temp` varchar(50) default NULL,
+ `employer_temp` varchar(50) default NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+
diff --git a/test/scanners/sql/maintenance.expected.raydebug b/test/scanners/sql/maintenance.expected.raydebug
new file mode 100644
index 0000000..81c3c8e
--- /dev/null
+++ b/test/scanners/sql/maintenance.expected.raydebug
@@ -0,0 +1,24 @@
+comment(--RANDOM SQL QUERIES THAT DO NOTHING INTERESTING)
+comment(--Copyright (C\) 2009 - Keith Pitt <keith@keithpitt.com>)
+
+comment(--This program is free software: you can redistribute it and/or modify)
+comment(--it under the terms of the GNU General Public License as published by)
+comment(--the Free Software Foundation, either version 3 of the License, or)
+comment(--(at your option\) any later version.)
+
+comment(--This program is distributed in the hope that it will be useful,)
+comment(--but WITHOUT ANY WARRANTY; without even the implied warranty of)
+comment(--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the)
+comment(--GNU General Public License for more details.)
+
+comment(--You should have received a copy of the GNU General Public License)
+comment(--along with this program. If not, see <http://www.gnu.org/licenses/>.)
+
+reserved(INSERT) reserved(INTO) (users) operator(()(first_name)operator(,) (last_name)operator(\)) reserved(VALUES) operator(()string<delimiter(')content(John)delimiter(')>operator(,) string<delimiter(')content(Doe)delimiter(')>operator(\))operator(;)
+
+reserved(INSERT) reserved(INTO) (users) operator(()(first_name)operator(,) (last_name)operator(\)) reserved(VALUES) operator(()string<delimiter(")content(John)delimiter(")>operator(,) string<delimiter(")content(Doe)delimiter(")>operator(\))operator(;)
+
+reserved(UPDATE) (users) reserved(SET) (first_name) operator(=) string<delimiter(')content(Keith)delimiter(')> reserved(WHERE) (first_name) operator(=) string<delimiter(')content(JOHN)delimiter(')>operator(;)
+
+reserved(DELETE) reserved(FROM) (users) reserved(WHERE) (first_name) operator(=) string<delimiter(')content(Keith)delimiter(')>operator(;)
+
diff --git a/test/scanners/sql/maintenance.in.sql b/test/scanners/sql/maintenance.in.sql
new file mode 100644
index 0000000..7b06db6
--- /dev/null
+++ b/test/scanners/sql/maintenance.in.sql
@@ -0,0 +1,24 @@
+--RANDOM SQL QUERIES THAT DO NOTHING INTERESTING
+--Copyright (C) 2009 - Keith Pitt <keith@keithpitt.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 3 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, see <http://www.gnu.org/licenses/>.
+
+INSERT INTO users (first_name, last_name) VALUES ('John', 'Doe');
+
+INSERT INTO users (first_name, last_name) VALUES ("John", "Doe");
+
+UPDATE users SET first_name = 'Keith' WHERE first_name = 'JOHN';
+
+DELETE FROM users WHERE first_name = 'Keith';
+
diff --git a/test/scanners/sql/reference.expected.raydebug b/test/scanners/sql/reference.expected.raydebug
new file mode 100644
index 0000000..ed8e195
--- /dev/null
+++ b/test/scanners/sql/reference.expected.raydebug
@@ -0,0 +1,109 @@
+comment(# All of the values below are valid MySQL syntax accoring to)
+comment(# the Reference Manual:)
+comment(# http://dev.mysql.com/doc/refman/5.1/en/language-structure.html)
+comment(# unless stated otherwise.)
+
+comment(# strings)
+reserved(SELECT) string<delimiter(')content(a string)delimiter(')>operator(;)
+reserved(SELECT) string<delimiter(")content(another string)delimiter(")>operator(;)
+
+reserved(SELECT) string<modifier(_latin1)delimiter(')content(string)delimiter(')>operator(;)
+reserved(SELECT) string<modifier(_latin1)delimiter(')content(string)delimiter(')> reserved(COLLATE) (latin1_danish_ci)operator(;)
+
+reserved(SELECT) string<modifier(N)delimiter(')content(some text)delimiter(')>operator(;)
+reserved(SELECT) string<modifier(n)delimiter(')content(some text)delimiter(')>operator(;)
+reserved(SELECT) string<modifier(_utf8)delimiter(')content(some text)delimiter(')>operator(;)
+
+reserved(SELECT) string<delimiter(")char(\\0)char(\\')char(\\")content(''"")char(\\b)char(\\n)char(\\r)char(\\t)char(\\Z)char(\\\\)char(\\%)char(\\_)delimiter(")>operator(;) comment(# ")
+reserved(SELECT) string<delimiter(')char(\\0)char(\\')char(\\")content(''"")char(\\b)char(\\n)char(\\r)char(\\t)char(\\Z)char(\\\\)char(\\%)char(\\_)delimiter(')>operator(;) comment(# ')
+
+reserved(SELECT) string<delimiter(")char(\\B)char(\\x)delimiter(")>operator(;) comment(# ")
+reserved(SELECT) string<delimiter(')char(\\B)char(\\x)delimiter(')>operator(;) comment(# ')
+
+reserved(SELECT) string<delimiter(')content(hello)delimiter(')>operator(,) string<delimiter(')content("hello")delimiter(')>operator(,) string<delimiter(')content(""hello"")delimiter(')>operator(,) string<delimiter(')content(hel''lo)delimiter(')>operator(,) string<delimiter(')char(\\')content(hello)delimiter(')>operator(;) comment(-- ')
+reserved(SELECT) string<delimiter(")content(hello)delimiter(")>operator(,) string<delimiter(")content('hello')delimiter(")>operator(,) string<delimiter(")content(''hello'')delimiter(")>operator(,) string<delimiter(")content(hel""lo)delimiter(")>operator(,) string<delimiter(")char(\\")content(hello)delimiter(")>operator(;) comment(-- ")
+
+reserved(SELECT) string<delimiter(')content(This)char(\\n)content(Is)char(\\n)content(Four)char(\\n)content(Lines)delimiter(')>operator(;)
+reserved(SELECT) string<delimiter(')content(disappearing)char(\\ )content(backslash)delimiter(')>operator(;)
+
+comment(# numbers)
+reserved(select) integer(1221)operator(;)
+reserved(select) integer(0)operator(;)
+reserved(select) operator(-)integer(32)error(:)
+
+reserved(select) float(294.42)error(:)
+reserved(select) operator(-)float(32032.6809e+10)operator(;)
+reserved(select) float(148.00)operator(;)
+
+reserved(select) float(10e+10)operator(;)
+reserved(select) float(10e10)operator(;)
+
+comment(# hexadecimal)
+reserved(SELECT) string<modifier(X)delimiter(')content(4D7953514C)delimiter(')>operator(;)
+reserved(SELECT) hex(0x0a)operator(+)integer(0)operator(;)
+reserved(SELECT) hex(0x5061756c)operator(;)
+reserved(SELECT) hex(0x41)operator(,) predefined(CAST)operator(()hex(0x41) reserved(AS) pre_type(UNSIGNED)operator(\))operator(;)
+reserved(SELECT) pre_type(HEX)operator(()string<delimiter(')content(cat)delimiter(')>operator(\))operator(;)
+reserved(SELECT) hex(0x636174)operator(;)
+reserved(insert) reserved(into) (t) operator(()(md5)operator(\)) reserved(values) operator(()hex(0xad65)operator(\))operator(;)
+reserved(SELECT) operator(*) reserved(FROM) (SomeTable) reserved(WHERE) (BinaryColumn) operator(=) predefined(CAST)operator(() string<modifier(x)delimiter(')content(a0f44ef7a52411de)delimiter(')> reserved(AS) pre_type(BINARY) operator(\))operator(;)
+reserved(select) string<modifier(x)delimiter(')content(000bdddc0e9153f5a93447fc3310f710)delimiter(')>operator(,) string<modifier(x)delimiter(')content(0bdddc0e9153f5a93447fc3310f710)delimiter(')>operator(;)
+
+reserved(SELECT) pre_constant(TRUE)operator(,) pre_constant(true)operator(,) pre_constant(FALSE)operator(,) pre_constant(false)operator(;)
+reserved(SELECT) pre_constant(NULL)operator(,) pre_constant(null)operator(,) pre_constant(nuLL)operator(,) error(\\)(N)operator(;)
+reserved(SELECT) error(\\)(n)operator(;) comment(# invalid!)
+
+comment(# bit-field)
+reserved(CREATE) reserved(TABLE) (t) operator(()(b) pre_type(BIT)operator(()integer(8)operator(\))operator(\))operator(;)
+reserved(INSERT) reserved(INTO) (t) reserved(SET) (b) operator(=) string<modifier(b)delimiter(')content(11111111)delimiter(')>operator(;)
+reserved(INSERT) reserved(INTO) (t) reserved(SET) (b) operator(=) string<modifier(b)delimiter(')content(1010)delimiter(')>operator(;)
+reserved(INSERT) reserved(INTO) (t) reserved(SET) (b) operator(=) string<modifier(b)delimiter(')content(0101)delimiter(')>operator(;)
+reserved(SELECT) (b)operator(+)integer(0)operator(,) pre_type(BIN)operator(()(b)operator(+)integer(0)operator(\))operator(,) pre_type(OCT)operator(()(b)operator(+)integer(0)operator(\))operator(,) pre_type(HEX)operator(()(b)operator(+)integer(0)operator(\)) reserved(FROM) (t)operator(;)
+
+reserved(SET) variable(@v1) operator(=) string<modifier(b)delimiter(')content(1000001)delimiter(')>operator(;)
+reserved(SET) variable(@v2) operator(=) predefined(CAST)operator(()string<modifier(b)delimiter(')content(1000001)delimiter(')> reserved(AS) pre_type(UNSIGNED)operator(\))operator(,) variable(@v3) operator(=) string<modifier(b)delimiter(')content(1000001)delimiter(')>operator(+)integer(0)operator(;)
+reserved(SELECT) variable(@v1)operator(,) variable(@v2)operator(,) variable(@v3)operator(;)
+
+reserved(INSERT) reserved(INTO) (my_table) operator(()(phone)operator(\)) reserved(VALUES) operator(()pre_constant(NULL)operator(\))operator(;)
+reserved(INSERT) reserved(INTO) (my_table) operator(()(phone)operator(\)) reserved(VALUES) operator(()string<delimiter(')delimiter(')>operator(\))operator(;)
+
+comment(# schema object names)
+reserved(SELECT) operator(*) reserved(FROM) string<delimiter(`)content(select)delimiter(`)> reserved(WHERE) string<delimiter(`)content(select)delimiter(`)>operator(.)(id) operator(>) integer(100)operator(;)
+
+reserved(CREATE) reserved(TABLE) string<delimiter(`)content(a``b)delimiter(`)> operator(()string<delimiter(`)content(c"d)delimiter(`)> pre_type(INT)operator(\))operator(;)
+reserved(SELECT) integer(1) reserved(AS) string<delimiter(`)content(one)delimiter(`)>operator(,) integer(2) reserved(AS) string<delimiter(')content(two)delimiter(')>operator(;)
+
+reserved(select) (foo) reserved(from) (foo)operator(;)
+reserved(select) string<delimiter(`)content(foo)delimiter(`)> reserved(from) (foo)operator(;)
+reserved(select) (foo)operator(.)(bar) reserved(from) (foo)operator(;)
+reserved(select) string<delimiter(`)content(foo)delimiter(`)>operator(.)(bar) reserved(from) (foo)operator(;)
+reserved(select) (foo)operator(.)string<delimiter(`)content(bar)delimiter(`)> reserved(from) (foo)operator(;)
+reserved(select) string<delimiter(`)content(foo.bar)delimiter(`)> reserved(from) (foo)operator(;)
+reserved(select) string<delimiter(`)content(foo)delimiter(`)>operator(.)string<delimiter(`)content(bar)delimiter(`)> reserved(from) (foo)operator(;)
+
+comment(# How to handle ANSI_QUOTES?)
+reserved(CREATE) reserved(TABLE) string<delimiter(")content(test)delimiter(")> operator(()(col) pre_type(INT)operator(\))operator(;)
+reserved(SET) (sql_mode)operator(=)string<delimiter(')content(ANSI_QUOTES)delimiter(')>operator(;)
+reserved(CREATE) reserved(TABLE) string<delimiter(")content(test)delimiter(")> operator(()(col) pre_type(INT)operator(\))operator(;)
+
+comment(# identifiers)
+reserved(SELECT) operator(*) reserved(FROM) (my_table) reserved(WHERE) (MY_TABLE)operator(.)(col)operator(=)integer(1)operator(;)
+reserved(SHOW) reserved(COLUMNS) reserved(FROM) string<delimiter(`)content(#mysql50#a@b)delimiter(`)>operator(;)
+
+comment(# Function Name Parsing and Resolution)
+
+
+reserved(SELECT) predefined(COUNT)operator(()operator(*)operator(\)) reserved(FROM) (mytable)operator(;) comment(-- the first reference to count is a function call)
+reserved(CREATE) reserved(TABLE) predefined(count) operator(()(i) pre_type(INT)operator(\))operator(;) comment(-- whereas the second reference is a table name)
+reserved(CREATE) reserved(TABLE) string<delimiter(`)content(count)delimiter(`)>operator(()(i) pre_type(INT)operator(\))operator(;) comment(-- this too)
+reserved(CREATE) reserved(TABLE) string<delimiter(`)content(count)delimiter(`)> operator(()(i) pre_type(INT)operator(\))operator(;) comment(-- this too)
+
+comment(# IGNORE_SPACE)
+reserved(SELECT) predefined(COUNT)operator(()operator(*)operator(\)) reserved(FROM) (mytable)operator(;)
+reserved(SELECT) predefined(COUNT) operator(()operator(*)operator(\)) reserved(FROM) (mytable)operator(;)
+
+comment(# reserved words)
+reserved(CREATE) reserved(TABLE) (interval) operator(()reserved(begin) pre_type(INT)operator(,) reserved(end) pre_type(INT)operator(\))operator(;) comment(-- errror)
+reserved(CREATE) reserved(TABLE) string<delimiter(`)content(interval)delimiter(`)> operator(()reserved(begin) pre_type(INT)operator(,) reserved(end) pre_type(INT)operator(\))operator(;) comment(-- valid)
+reserved(CREATE) reserved(TABLE) (mydb)operator(.)(interval) operator(()reserved(begin) pre_type(INT)operator(,) reserved(end) pre_type(INT)operator(\))operator(;) comment(-- valid)
+reserved(SELECT) string<delimiter(`)content(foo)delimiter(`)>operator(,) string<delimiter(`)content(bar)delimiter(`)> reserved(FROM) string<delimiter(`)content(baz)delimiter(`)> reserved(WHERE) string<delimiter(`)content(bal)delimiter(`)> operator(=) string<delimiter(`)content(quiche)delimiter(`)>operator(;) comment(-- valid)
diff --git a/test/scanners/sql/reference.in.sql b/test/scanners/sql/reference.in.sql
new file mode 100644
index 0000000..e301570
--- /dev/null
+++ b/test/scanners/sql/reference.in.sql
@@ -0,0 +1,109 @@
+# All of the values below are valid MySQL syntax accoring to
+# the Reference Manual:
+# http://dev.mysql.com/doc/refman/5.1/en/language-structure.html
+# unless stated otherwise.
+
+# strings
+SELECT 'a string';
+SELECT "another string";
+
+SELECT _latin1'string';
+SELECT _latin1'string' COLLATE latin1_danish_ci;
+
+SELECT N'some text';
+SELECT n'some text';
+SELECT _utf8'some text';
+
+SELECT "\0\'\"''""\b\n\r\t\Z\\\%\_"; # "
+SELECT '\0\'\"''""\b\n\r\t\Z\\\%\_'; # '
+
+SELECT "\B\x"; # "
+SELECT '\B\x'; # '
+
+SELECT 'hello', '"hello"', '""hello""', 'hel''lo', '\'hello'; -- '
+SELECT "hello", "'hello'", "''hello''", "hel""lo", "\"hello"; -- "
+
+SELECT 'This\nIs\nFour\nLines';
+SELECT 'disappearing\ backslash';
+
+# numbers
+select 1221;
+select 0;
+select -32:
+
+select 294.42:
+select -32032.6809e+10;
+select 148.00;
+
+select 10e+10;
+select 10e10;
+
+# hexadecimal
+SELECT X'4D7953514C';
+SELECT 0x0a+0;
+SELECT 0x5061756c;
+SELECT 0x41, CAST(0x41 AS UNSIGNED);
+SELECT HEX('cat');
+SELECT 0x636174;
+insert into t (md5) values (0xad65);
+SELECT * FROM SomeTable WHERE BinaryColumn = CAST( x'a0f44ef7a52411de' AS BINARY );
+select x'000bdddc0e9153f5a93447fc3310f710', x'0bdddc0e9153f5a93447fc3310f710';
+
+SELECT TRUE, true, FALSE, false;
+SELECT NULL, null, nuLL, \N;
+SELECT \n; # invalid!
+
+# bit-field
+CREATE TABLE t (b BIT(8));
+INSERT INTO t SET b = b'11111111';
+INSERT INTO t SET b = b'1010';
+INSERT INTO t SET b = b'0101';
+SELECT b+0, BIN(b+0), OCT(b+0), HEX(b+0) FROM t;
+
+SET @v1 = b'1000001';
+SET @v2 = CAST(b'1000001' AS UNSIGNED), @v3 = b'1000001'+0;
+SELECT @v1, @v2, @v3;
+
+INSERT INTO my_table (phone) VALUES (NULL);
+INSERT INTO my_table (phone) VALUES ('');
+
+# schema object names
+SELECT * FROM `select` WHERE `select`.id > 100;
+
+CREATE TABLE `a``b` (`c"d` INT);
+SELECT 1 AS `one`, 2 AS 'two';
+
+select foo from foo;
+select `foo` from foo;
+select foo.bar from foo;
+select `foo`.bar from foo;
+select foo.`bar` from foo;
+select `foo.bar` from foo;
+select `foo`.`bar` from foo;
+
+# How to handle ANSI_QUOTES?
+CREATE TABLE "test" (col INT);
+SET sql_mode='ANSI_QUOTES';
+CREATE TABLE "test" (col INT);
+
+# identifiers
+SELECT * FROM my_table WHERE MY_TABLE.col=1;
+SHOW COLUMNS FROM `#mysql50#a@b`;
+
+# Function Name Parsing and Resolution
+
+
+SELECT COUNT(*) FROM mytable; -- the first reference to count is a function call
+CREATE TABLE count (i INT); -- whereas the second reference is a table name
+CREATE TABLE `count`(i INT); -- this too
+CREATE TABLE `count` (i INT); -- this too
+
+# IGNORE_SPACE
+SELECT COUNT(*) FROM mytable;
+SELECT COUNT (*) FROM mytable;
+
+# reserved words
+CREATE TABLE interval (begin INT, end INT); -- errror
+CREATE TABLE `interval` (begin INT, end INT); -- valid
+CREATE TABLE mydb.interval (begin INT, end INT); -- valid
+SELECT `foo`, `bar` FROM `baz` WHERE `bal` = `quiche`; -- valid
diff --git a/test/scanners/sql/selects.expected.raydebug b/test/scanners/sql/selects.expected.raydebug
new file mode 100644
index 0000000..4bbd89d
--- /dev/null
+++ b/test/scanners/sql/selects.expected.raydebug
@@ -0,0 +1,46 @@
+comment(--RANDOM SQL QUERIES THAT DO NOTHING INTERESTING)
+comment(--Copyright (C\) 2009 - Keith Pitt <keith@keithpitt.com>)
+
+comment(--This program is free software: you can redistribute it and/or modify)
+comment(--it under the terms of the GNU General Public License as published by)
+comment(--the Free Software Foundation, either version 3 of the License, or)
+comment(--(at your option\) any later version.)
+
+comment(--This program is distributed in the hope that it will be useful,)
+comment(--but WITHOUT ANY WARRANTY; without even the implied warranty of)
+comment(--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the)
+comment(--GNU General Public License for more details.)
+
+comment(--You should have received a copy of the GNU General Public License)
+comment(--along with this program. If not, see <http://www.gnu.org/licenses/>.)
+
+reserved(SELECT) operator(*) reserved(FROM) (users)operator(;)
+
+reserved(select) operator(*) reserved(from) (users)operator(;)
+
+reserved(SELECT) string<delimiter(`)content(First Name)delimiter(`)>operator(,) string<delimiter(`)content(Last Name)delimiter(`)> reserved(FROM) string<delimiter(`)content(User Table)delimiter(`)>operator(;)
+
+reserved(select) (first_name)operator(,) (last_name) reserved(FROM) (users)operator(;)
+
+reserved(select) (first_name) operator(|)operator(|) string<delimiter(')content( )delimiter(')> operator(|)operator(|) (last_name) reserved(from) (users)operator(;)
+
+reserved(select) (first_name) operator(|)operator(|) string<delimiter(")content( )delimiter(")> operator(|)operator(|) (last_name) reserved(from) (users)operator(;)
+
+reserved(SELECT) operator(*) reserved(FROM) (users) reserved(JOIN) (companies) reserved(USING) operator(()(company_id)operator(\)) reserved(WHERE) (company_type) operator(=) string<delimiter(')content(Fortune 500)delimiter(')>operator(;)
+
+reserved(SELECT) operator(*) reserved(FROM) (users) reserved(WHERE) (name_first) reserved(LIKE) string<delimiter(')content(%Keith%)delimiter(')>operator(;)
+
+reserved(SELECT) reserved(CASE) reserved(WHEN) (foo)operator(.)(bar) operator(=) string<delimiter(')content(PY)delimiter(')>
+ reserved(THEN) string<delimiter(')content(BAR)delimiter(')>
+ reserved(ELSE) string<delimiter(')content(FOO)delimiter(')>
+ reserved(END) reserved(as) (bar_type)operator(,)
+ (user_id)operator(,)
+ (company_id)operator(,)
+ predefined(sum)operator(()
+ reserved(case) reserved(when) (foo)operator(.)(bar) operator(=) string<delimiter(')content(PY)delimiter(')>
+ reserved(then) operator(-)(amt) reserved(else) (amt)
+ reserved(end)
+ operator(\)) (over) operator(()reserved(order) reserved(by) (id)operator(,) (amt)operator(\)) reserved(as) (balance)operator(;)
+
+reserved(SELECT) (users)operator(.)operator(*)operator(,) operator(()reserved(SELECT) (company_name) reserved(FROM) (companies) reserved(WHERE) (company_id) operator(=) (users)operator(.)(company_id)operator(\)) reserved(FROM) (users)operator(;)
+
diff --git a/test/scanners/sql/selects.in.sql b/test/scanners/sql/selects.in.sql
new file mode 100644
index 0000000..3c6203f
--- /dev/null
+++ b/test/scanners/sql/selects.in.sql
@@ -0,0 +1,46 @@
+--RANDOM SQL QUERIES THAT DO NOTHING INTERESTING
+--Copyright (C) 2009 - Keith Pitt <keith@keithpitt.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 3 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, see <http://www.gnu.org/licenses/>.
+
+SELECT * FROM users;
+
+select * from users;
+
+SELECT `First Name`, `Last Name` FROM `User Table`;
+
+select first_name, last_name FROM users;
+
+select first_name || ' ' || last_name from users;
+
+select first_name || " " || last_name from users;
+
+SELECT * FROM users JOIN companies USING (company_id) WHERE company_type = 'Fortune 500';
+
+SELECT * FROM users WHERE name_first LIKE '%Keith%';
+
+SELECT CASE WHEN foo.bar = 'PY'
+ THEN 'BAR'
+ ELSE 'FOO'
+ END as bar_type,
+ user_id,
+ company_id,
+ sum(
+ case when foo.bar = 'PY'
+ then -amt else amt
+ end
+ ) over (order by id, amt) as balance;
+
+SELECT users.*, (SELECT company_name FROM companies WHERE company_id = users.company_id) FROM users;
+
diff --git a/test/scanners/sql/suite.rb b/test/scanners/sql/suite.rb
new file mode 100644
index 0000000..f1122b3
--- /dev/null
+++ b/test/scanners/sql/suite.rb
@@ -0,0 +1,2 @@
+class SQL < CodeRay::TestCase
+end