Professional Documents
Culture Documents
REXX
Objectives
Introduction to REXX
Advanced Concepts
2/16/2011 2
Introduction
What is REXX ?
± Restructured EXtended eXecutor
± Interpreted command language
± Very useful for linking TSO, ISPF and other
functions
± Useful for developing custom-made utilities
2/16/2011 3
Features of REXX
Ease of use
Free format
2/16/2011 4
Features of REXX (Cont...)
Debugging capabilities
Interpreted language
2/16/2011 5
Components of REXX
Instructions
Built-in functions
TSO functions
Data stack functions
2/16/2011 6
Instruction
Keyword
± Tells the language processor to do something
Assignment
± Gives a value to a variable or changes the current
value of a variable
Label
± A symbolic name followed by a colon
± Identifies a portion of the exec
± Commonly used in subroutines and functions, and
with the CALL/SIGNAL instruction
2/16/2011 7
Instruction (Cont...)
2/16/2011 8
Built-in functions
2/16/2011 9
TSO external functions
2/16/2011 10
Data stack functions
2/16/2011 11
2/16/2011 12
Syntax of REXX
Character Type of REXX
A REXX instruction can be in lower case, upper
case, or mixed case
Alphabetic characters are changed to uppercase,
unless enclosed in single or double quotation
marks
The two types of quotation marks cannot be
mixed
If any word in the statement is a variable, REXX
substitutes the value
2/16/2011 13
Format
REXX uses a free format
A line usually contains one instruction except
when it ends with a comma (,) or contains a
semi-colon (;).
± Comma is the continuation character
± Indicates that the instruction continues to the next line
± Semi-colon indicates the end of the instruction
± Used to separate multiple instructions on one line
2/16/2011 14
Environment / Address
2/16/2011 15
2/16/2011 16
2/16/2011 17
Variables (Cont...)
2/16/2011 18
Parsing
Separates data by comparing the data to a
template (or pattern of variable names)
Preserves the case of the input data
PARSE UPPER converts data to uppercase
Separators in a template can be
± blank,
± string,
± variable, or
± number that represents column position
2/16/2011 19
Parsing
Blank - an example
± Each variable name gets one word of data in
sequence except for the last, which gets the remainder
of the data
± PARSE VALUE µValue with Blanks.¶ WITH
pattern type
pattern contains µValue¶
type contains µ with Blanks.¶
2/16/2011 20
Parsing
2/16/2011 21
Parsing
Substitution - an example
± PARSE VALUE µValue with Periods in it.¶ WITH
pattern . type .
± pattern contains µValue¶
± type contains µPeriods¶
± the periods replace the words ³with´ and ³in it.´
2/16/2011 22
Parsing
Separators - an example
± phrase = µDun & Bradstreet¶
± PARSE VAR phrase part1 µ&¶ part2
± part1 contains µDun ¶
± part2 contains µ Bradstreet¶
2/16/2011 23
Parsing
2/16/2011 24
Parsing
Absolute column position
± An unsigned integer or an integer prefixed with an
equal sign (=) in a template
± The first segment starts at column 1 and goes up to,
but does not include, the information in the column
number specified
± The subsequent segments start at the column
numbers specified
2/16/2011 25
Parsing
2/16/2011 26
Parsing
2/16/2011 27
Parsing
2/16/2011 28
Parsing
2/16/2011 29
Parsing
Variables
± Define and use variables to provide further flexibility
of a PARSE VAR instruction
± Define the variable prior to the parse instruction
± Enclose the variable in parenthesis - this variable
must be an unsigned integer
± Use a sign outside the parenthesis to indicate how
REXX is to interpret the unsigned integer
± REXX substitutes the numeric value for the variable
2/16/2011 30
Parsing
Variables - an example
± quote = µDun & Bradstreet¶
± movex = 4
± PARSE VAR quote part5 +6 part6 +4 part7
-(movex) part8
± part5 contains µDun &¶
± part6 contains µBrad¶
± part7 contains µstreet¶
± part8 contains µBradstreet¶
2/16/2011 31
Expressions
2/16/2011 33
Arithmetic Operators (Cont...)
±* Multiply
± ** Raise a number to a whole number power
± / Divide
±% Divide and return a whole number without a
remainder (quotient only)
± // Divide and return the remainder only
2/16/2011 34
Arithmetic Operators -
Priority
2/16/2011 35
Comparison operators
Do not return a number value
Return either a true or false response in terms of
1 or 0 respectively
± == Strictly Equal
±= Equal
±> Greater than
±< Less than
± >= Greater than or equal to
± <= Less than or equal to
2/16/2011 36
Comparison operators (Cont...)
2/16/2011 37
Strictly Equal and Equal Operators
2/16/2011 38
Logical Operators
Return a true (1) or false (0) value when
processed
Combine two comparisons and return the true (1)
or false (0) value depending on the results of the
comparisons
Used in complex conditional instructions
Can act as checkpoints to screen unwanted
conditions
2/16/2011 39
Logical Operators (Cont...)
The logical operators are
±& AND
Returns 1 if both comparisons are true
±| Inclusive OR
Returns 1 if at least one comparison is true
± && Exclusive OR
Returns 1 if only one comparison (but not both) is
true
± Prefix \ Logical NOT
Returns the opposite response
2/16/2011 40
Concatenation operators
2/16/2011 41
Concatenation operators (Cont...)
2/16/2011 42
Overall Operator Priority
\ ¬ - + Prefix operators
** Power (exponential)
* / % // Multiply and divide
+ - Add and subtract
blank || abuttal Concatenation
operators
== = >< Comparison operators
& Logical AND
| && inclusive OR, exclusive OR
2/16/2011 43
2/16/2011 44
Control of
program flow
Conditional instructions
Instructions which set up at least one condition in
the form of an expression
IF/THEN/ELSE, and
SELECT/WHEN/OTHERWISE
2/16/2011 45
IF construct
Can direct the execution of an exec to one of two
choices
IF expression
THEN instruction
ELSE instruction
for more than one instruction for a condition,
begin the set of instructions with a DO and end
them with an END
2/16/2011 46
IF construct (Cont...)
IF expression THEN
DO
instruction
instruction
END
ELSE
DO
instruction
instruction
END
2/16/2011 47
SELECT construct
can direct the execution to one of many choices.
SELECT
WHEN expression THEN instruction
WHEN expression THEN instruction
:
OTHERWISE
instruction(s)
END
2/16/2011 48
SELECT construct
2/16/2011 49
Looping instructions
Tell the language processor to repeat a set of
instructions
A loop can repeat a specified number of times or
Can use a condition to control repeating
Two types of loops
± Repetitive repeat instructions a certain number of
times
± Conditional use a condition to control repeating
2/16/2011 50
Repetitive loops
Repeat a set of instructions a specified number of
times
± e.g. DO i = 1 to 5
SAY ³Hello !´
END
The step can also be controlled
e.g. DO i = 1 to 10 STEP 2
SAY ³Hello !´
END
2/16/2011 51
Repetitive loops
DO FOREVER/END - infinite loops
EXIT when a condition is reached
LEAVE instruction - leaves the loop
e.g. DO FOREVER
IF X = 0 THEN LEAVE
2/16/2011 52
Conditional loops
DO WHILE
± DO WHILE expression
instruction(s)
END
± Test the expression before the loop executes the first
time and repeat only when the expression is true
2/16/2011 53
Conditional loops
DO UNTIL
± DO UNTIL expression
instruction(s)
END
± Test the expression after the loop executes at least
once and repeat only when the expression is false
2/16/2011 54
Interrupt instructions
Tell the language processor to leave the exec
entirely or
leave one part of the exec and go to another part
either permanently or temporarily
These are
± EXIT
± SIGNAL
± CALL/RETURN
2/16/2011 55
EXIT
2/16/2011 56
SIGNAL label
2/16/2011 57
CALL / RETURN
2/16/2011 58
CALL / RETURN
2/16/2011 59
2/16/2011 60
2/16/2011 64
2/16/2011 65
Built-in functions
Arithmetic functions
ABS Returns the absolute value of the
input number
MAX Returns the largest number from
the list
MIN Returns the smallest number from
the list specified
2/16/2011 66
Arithmetic functions
2/16/2011 67
Arithmetic functions
RANDOM() Returns a quasi-random, non-
negative whole number in the range specified
TRUNC(12.3) -> 12
TRUNC(127.09782,3) -> 127.097
TRUNC(127.1,3) -> 127.100
TRUNC(127,2) -> 127.00
2/16/2011 69
Comparison functions
COMPARE
± Returns 0 if the two input strings are identical
± Returns the position of the first character that does
not match
COMPARE(ACC,ACD) /* 3 */
DATATYPE(123) /* NUM OR CHAR */
A.3=5; J=3 ;
SYMBOL('J') /* VAR */
SYMBOL('K') /* LIT */
SYMBOL('A.J') /* VAR */
SYMBOL('552') /* LIT CONSTANT SYMBOL */
SAY SYMBOL('+') /* BAD NOT A VALID SYMBOL */
2/16/2011 71
Conversion functions
2/16/2011 72
Conversion functions
2/16/2011 73
Conversion functions
M= B2X(0101) ; SAY M /* BINARY TO HEXADECIMAL 5 */
M= C2D(ABC); SAY M /* CHARACTER TO DECIMAL 12698307 */
M= C2X(ABC); SAY M /* CHARACTER TO HEXADECIMAL C1C2C3 */
M= D2C(123); SAY M /* DECIMAL TO CHARACTER # */
M= D2X(123); SAY M /* DECIMAL TO HEXADECIMAL 7B */
M = X2B(ABC); SAY M /* HEXADECIMAL TO BINARY 101010111100 */
M = X2C(ABC); SAY M /* HEXADECIMAL TO CHARACTER :: */
M = X2D(ABC); SAY M /* HEXADECIMAL TO DECIMAL 2748 */
2/16/2011 74
Formatting functions
CENTER/CENTRE
Returns a string of a specified length with the
input string centered in it, with pad characters
added as necessary to make up the length
2/16/2011 76
Formatting functions
2/16/2011 77
Formatting functions
2/16/2011 78
Formatting functions
ë
ë
ë
ë
!
!
"
!
!
!
2/16/2011 79
String manipulating functions
ABBREV Returns a string indicating if
one string is equal to the specified number of
leading characters of another string
INDEX('abcdef','cd') -> 3
INDEX('abcdef','xd') -> 0
INDEX('abcabc','bc',3) -> 5
INDEX('abcabc','bc',6) -> 0
2/16/2011 84
String manipulating functions
LASTPOS(' ','abc def ghi') -> 8
LASTPOS(' ','abcdefghi') -> 0
LASTPOS('xy','efgxyz') -> 4
LASTPOS(' ','abc def ghi',7) -> 4
LENGTH('abcdefgh') -> 8
LENGTH('abc defg') -> 8
LENGTH('') -> 0
2/16/2011 87
String manipulating functions
SUBSTR Returns a portion of the
input string beginning at a specified character
position
2/16/2011 94
Date formats
Base(or Basedate) Returns the number of
complete days (that is, not including the current
day) since and including the date, January 1,
0001, in the format: dddddd (no leading zeros or
blanks)
± The expression DATE(µB¶)//7 returns a number in the
range 0-6, where 0 is Monday and 6 is Sunday
± Thus, this function can be used to determine the day
of the week independent of the language
2/16/2011 95
Date formats
Century Returns the number of days,
including the current day, since and including
January 1 of the last year that is a multiple of 100
in the format: ddddd (no leading zeros)
Example: A call to DATE(C) is made on March
13, 1992, so the number of days from January 1,
1900, to March 13, 1992, (33675) is returned
2/16/2011 99
Time formats
Civil
± Returns the time in Civil format: hh:mmxx
± The hours take the values 1 through 12
± The minutes take the values 00 through 59
± The minutes are followed immediately by the letters
am or pm
± The hour has no leading zero
± The minute field shows the current minute (rather
than the nearest minute) for consistency with other
TIME results
2/16/2011 100
Time formats
Elapsed
± Returns sssssssss.uuuuuu, the number of
seconds.microseconds since the elapsed-time clock
was started or reset
± No leading zeros or blanks
± Setting of NUMERIC DIGITS does not affect the
number
± The fractional part always has six digits
2/16/2011 101
Time formats
Hours
± Returns up to two characters
± Gives the number of hours since midnight
± Format is hh
± No leading zeros or blanks, except for a result of 0
2/16/2011 102
Time formats
Long
± Returns time in the format: hh:mm:ss.uuuuuu
(uuuuuu is in microseconds)
± The first eight characters of the result follow the same
rules as for the Normal form
± The fractional part is always six digits
2/16/2011 103
Time formats
Minutes
± Returns up to four characters
± Gives the number of minutes since midnight
± Format is mmmm
± No leading zeros or blanks, except for a result of 0
2/16/2011 104
Time formats
Normal
± This is the default
± Returns the time in the format hh:mm:ss
± Hours take the values 00 through 23
± Minutes and seconds take 00 through 59
± All these are always two digits
± Any fractions of seconds are ignored (times are never
rounded up)
2/16/2011 105
Time formats
Reset
± Returns sssssssss.uuuuuu, the number of
seconds.microseconds since the elapsed-time clock
was started or reset
± Also resets the elapsed-time clock to zero
± The number has no leading zeros or blanks
± Setting of NUMERIC DIGITS does not affect the
number
± The fractional part always has six digits
2/16/2011 106
Time formats
Seconds
± Returns up to five characters
± Gives the number of seconds since midnight
± Format is sssss
± No leading zeros or blanks, except for a result of 0
2/16/2011 107
2/16/2011 108
Subroutines
Subroutines
Series of instructions that an exec invokes
Performs a specific task
The subroutine is invoked by the CALL
instruction
When the subroutine ends, it returns control to
the instruction that directly follows the
subroutine call
The instruction that returns control is the
RETURN instruction
2/16/2011 109
Subroutines
Subroutines may be
± Internal and designated by a label, or
± external and designated by the member name that
contains the subroutine
IMPORTANT NOTE
± Internal subroutines generally appear after the main
part of the exec. So, when there is an internal
subroutine, it is important to end the main part of the
exec with the EXIT instruction
2/16/2011 110
Using subroutines
Sharing information can be done by
± Passing variables
± Passing arguments
2/16/2011 111
Passing Variables
Main exec and subroutine share the same
variables by name
2/16/2011 112
An example
NUMBER1 = 5
NUMBER2 = 10
CALL SUB1
SAY ANSWER
(DISPLAYS 15)
EXIT
SUB1:
ANSWER = NUMBER1
+ NUMBER2
RETURN
2/16/2011 113
Shielding Variables
2/16/2011 114
An example
NUMBER1 = 10
CALL SUB2
SAY NUMBER1 NUMBER2
(DISPLAYS 10 NUMBER2)
EXIT
SUB2: PROCEDURE
NUMBER1 = 7
NUMBER2 = 5
RETURN
2/16/2011 115
Exposing Variables
2/16/2011 116
An example
NUMBER1 = 10
CALL SUB3
SAY NUMBER1 NUMBER2
(DISPLAYS 7 NUMBER2)
EXIT
SUB3: PROCEDURE
EXPOSE NUMBER1
NUMBER1 = 7
NUMBER2 = 5
2/16/2011
RETURN 117
Passing Arguments
Passed in main EXEC by
± CALL subroutine_name argument1, argument2,
argument3, etc.
± Up to 20 arguments can be passed
Received in subroutine by
± ARG arg1, arg2, arg3, etc.
± The names of the arguments on the CALL and the
ARG instructions need not be the same
± information is passed by position, and not by name
2/16/2011 118
An example
LENGTH = 10
WIDTH = 7
CALL SUB4 LENGTH, WIDTH
SAY µTHE PERIMETER IS µ RESULT
µMETERS¶
EXIT
SUB4:
ARG LEN, WID
PERIM = 2 * ( LEN + WID)
RETURN PERIM
2/16/2011 119
Compound variables
ð !
ð "#$
ð %
ð &'
ð ()
2/16/2011 121
2/16/2011 122
Using REXX
Conventions
2/16/2011 123
Concatenations
2/16/2011 124
Execution
2/16/2011 125
Online Execution
2/16/2011 126
Batch Execution
66ë#
66!
$
!%&
ë
66!'
# &(
66!
# &(
66#
# &(
66'
(
$
)$$$$$$ $$% $$)
66(
2/16/2011 127
Data stack
2/16/2011 128
Data Stack
O
O
O
O
O
O
O
2/16/2011 129
Data stack
PUSH works LIFO (Last-In-First-Out)
± puts items to the top of the stack
*
%
*
%
+' , +
*
%"
6(#(6
*
%
!
%
6(#(6
!
!
!
!
!
+ +
!
+ +
!
$
2/16/2011 131
Input/Output processing
2/16/2011 132
DISKR
EXECIO DISKR for reading the dataset/member
± ³EXECIO 0 DISKR mydd (OPEN´ - just opens the
dataset
± ³EXECIO 25 ...´- reads 25 lines
± ³EXECIO * ...´ - reads all the lines
± ³EXECIO * DISKR myindd 100 (FINIS´ - reads
all lines from line 100
In all the above cases, the lines are read on to the STACK
± ³EXECIO * DISKR myindd (STEM newvar.´ -
reads into a stem of variables called newvar
2/16/2011 133
DISKW
2/16/2011 134
Example
Use REXX to
± List all datasets following a particular pattern
± For each dataset, list all the members starting with a
particular pattern
'
'#
6('&+%#- +
'#&+!$$%#- +
(6
%'.'/
'.'
#
ë&
#
% %
%'.'
$ %!&!% %ë
$
'.'/
'%
&
++
44
'%
44
++
#!
'!
#!
% %
#'%
&
++
44
#'%
44
++
!#&'
#!
'!
+#
''!
'+'% +
+
#
+ $ #
(
'!
%
'!
'+
+
''!+
+
+0123+
% % +
+#
'#'!
'+#'% +
&# !+#+
+
% %
+ $ #
(
,
#'!
%
'!
'+
'
+
'#'!+
#!
'!
'
'
2/16/2011 136
Debugging REXX Execs
Trace ?I (Intermediates)
± Stops execution after each instruction
Trace ?R (Results)
± Displays the result of execution of each step, but runs
continuously
These help to trace the progress of the EXEC
EXECUTIL TS (Trace start) and TE (trace end)
can also be used to start and end the tracing of a
REXX
2/16/2011 137
Debugging REXX Execs
2/16/2011 138
TSO External functions
2/16/2011 139
LISTDS µXXX.XXX.REXX' STATUS
XXX.XXX.REXX
--RECFM-LRECL-BLKSIZE-DSORG--DDNAME---DISP
FB 80 27920 PO SYS00007 KEEP
--VOLUMES--
TPT047
2/16/2011 140
2/16/2011 141
ISPF functions
Panels
2/16/2011 142
! $
' '
## #,
! $
' '
##!'
! $
' '
##
! # !
' '
## *
! $
' '
##,
! (
! $
' '#,
##
-
! '!
' '#,
## *
! $
' '#,
! $
' '
##,
' #
#%%'
&&.!%
(
%'!'
(
:
/9
:
/9
5
;
:
% /9%
6#!#'
&&.#
$ :
7
!
#
'
:
7
!
ë#
'
%
'
! #&#
<!%&
<#&
!#
-!
#
!#
- <#'"
'
2/16/2011 143
)ATTR
Panel example
@ TYPE(OUTPUT) INTENS(HIGH)
# TYPE(OUTPUT) INTENS(LOW) COLOR(YELLOW)
* TYPE(TEXT) INTENS(LOW) COLOR(GREEN) HILITE(REVERSE)
TYPE(OUTPUT) INTENS(LOW) COLOR(TURQ)
% TYPE(TEXT) INTENS(LOW) COLOR(TURQ) HILITE(USCORE)
+ TYPE(TEXT) INTENS(LOW)
)BODY
+-----------------* ARRAY OF VARIABLES +--------------------------+
+COMMAND ==>_ZCMD +SCROLL ==>_SAMT +
++
+JOBNAME1 STEP1 PGM1 DDN1 DSN1 DISP1
)MODEL
@JOBNAME1 #STEP1 PGM1 @DDN1 #DSN1 DISP
)INIT
&SAMT=CSR
&ZCMD=''
)END
2/16/2011 144
Tables
2/16/2011 145
ISPF Tables - Syntax
+! $
!
=$$$$$$+
+
+! $
!
=$$$$$$+
+
# %'
&
+
+
+! $
+ %!++
+! $
+ %!+
'% +# %'+
, +
+! $
#! '
= %!+
'#, +
&%
+! $
= %!+
' $
'% #' *+
+! $
'
= %!++
+! $
+ %!++
+! $
##%
+ %!++
+! $
#
+ %!++
+! $
#! '
+ %!+
'#, +
+! $
!
+ %!+
!' !' +
+! $
!
+ %!+
+! $
#
+ %!++
2/16/2011 146
Skeletons
ISPF Skeleton services like generating JCLs
from skeletons
Syntax is
± ADDRESS ISPEXEC
± ³FTOPEN´
± ³FTINCL SKELNAME´
± ³FTCLOSE TEMP´
± ADDRESS TSO
± ³SUBMIT ZTEMPF´
2/16/2011 147
File Tailoring Example:
/*REXX*/
"ISPEXEC LIBDEF ! DATASET ID('PXX.XXX.SKEL')
UNCOND"
!%&+
ë +
"ISPEXEC FTOPEN TEMP"
"ISPEXEC FTINCL !"
"ISPEXEC FTCLOSE"
"ISPEXEC VGET (ZTEMPF)"
SAY ZTEMPF
"SUBMIT '"ZTEMPF"'"
EXIT
2/16/2011 148
File Tailoring Example:
Skeleton ! :
//SKELJCL JOB ('245T01',53),'SKELJCL',CLASS=T,
// MSGCLASS=T,REGION=0M,NOTIFY=&SYSUID
//*
//ISPF1 EXEC PGM=<!%
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//SYSTSIN DD *
EX µXXX.XXX.REXX(MYREXX)'
//*
2/16/2011 149
ISREDIT Macros
2/16/2011 150
Macro Example:
/*REXX*/
ARG DSNAME1
ADDRESS ISPEXEC "EDIT DATASET('"DSNAME1"')
MACRO(%#)"
<< INSTRUCTION >>
<< INSTRUCTION >>
<< INSTRUCTION >>
EXIT
2/16/2011 151
Macro Example:
%#
/*REXX*/
ADDRESS ISPEXEC
"ISREDIT MACRO"
"ISREDIT FIND FIRST 'ENVIRONSYSTEM'"
"ISREDIT X ALL ' ' 47 70 "
"ISREDIT DEL ALL X"
"ISREDIT C ALL ' ' 87 90 '****'"
"ISREDIT SAVE"
"ISREDIT END"
"ISREDIT MEND"
2/16/2011 152
Messages:
2/16/2011 153
Message Example
% $$/
"ISPEXEC LIBDEF ISPMLIB DATASET ID(³XXX.XXX.MESG") "
If SYSDSN(PPP.PPP.PP) /= µOK¶ THEN
³ISPEXEC SETMSG MSG(% ) ³
% :
% 'NO DATASET' .ALARM=YES
µDATA SET IS NOT CATALOGUED ON THE DEVICE'
2/16/2011 154
LM Functions
Dataset list
Member list
± Copy members
± Delete members
± manipulate statistics of members
2/16/2011 155
LMDLIST - Example
/*REXX*/
LVL = USERID()
"ISPEXEC LMDINIT LISTID(ABC) LEVEL("LVL")"
"ISPEXEC LMDLIST LISTID("ABC") OPTION(SAVE)
STATS(YES) GROUP(%)"
/* THE OUTPUT WILL BE IN HLQ.%.DATASETS*/
"ISPEXEC LMDFREE LISTID("ABC")"
EXIT
2/16/2011 156
LMMLIST - Example
/*REXX*/
DSN="µXXX.XXX.LIST'"
"ISPEXEC LMINIT DATAID(ABC) DATASET("DSN") "
"ISPEXEC LMOPEN DATAID("ABC")"
"ISPEXEC LMMLIST DATAID("ABC") OPTION(SAVE)
STATS(YES) GROUP(AMD)"
/* THE OUTPUT WILL BE IN HLQ.AMD.MEMBERS */
"ISPEXEC LMFREE DATAID("ABC")"
EXIT
2/16/2011 157
LMCOPY - Example
/*REXX*/
ARG DSNI DSNO
ADDRESS TSO
"ISPEXEC LMINIT DATASET('"DSNI"') DATAID(INP) ENQ(SHR)"
"ISPEXEC LMINIT DATASET('"DSNO"') DATAID(OUT)
ENQ(EXCLU)"
"ISPEXEC LMCOPY FROMID("INP")
FROMMEM(MEM1)
TODATAID("OUT")
TOMEM(MEM2) REPLACE"
EXIT
2/16/2011 158
References
2/16/2011 159
2/16/2011 160
Thank
You!