1*0Sstevel@tonic-gate=head1 NAME 2*0Sstevel@tonic-gate 3*0Sstevel@tonic-gateperlsyn - Perl syntax 4*0Sstevel@tonic-gate 5*0Sstevel@tonic-gate=head1 DESCRIPTION 6*0Sstevel@tonic-gate 7*0Sstevel@tonic-gateA Perl program consists of a sequence of declarations and statements 8*0Sstevel@tonic-gatewhich run from the top to the bottom. Loops, subroutines and other 9*0Sstevel@tonic-gatecontrol structures allow you to jump around within the code. 10*0Sstevel@tonic-gate 11*0Sstevel@tonic-gatePerl is a B<free-form> language, you can format and indent it however 12*0Sstevel@tonic-gateyou like. Whitespace mostly serves to separate tokens, unlike 13*0Sstevel@tonic-gatelanguages like Python where it is an important part of the syntax. 14*0Sstevel@tonic-gate 15*0Sstevel@tonic-gateMany of Perl's syntactic elements are B<optional>. Rather than 16*0Sstevel@tonic-gaterequiring you to put parentheses around every function call and 17*0Sstevel@tonic-gatedeclare every variable, you can often leave such explicit elements off 18*0Sstevel@tonic-gateand Perl will figure out what you meant. This is known as B<Do What I 19*0Sstevel@tonic-gateMean>, abbreviated B<DWIM>. It allows programmers to be B<lazy> and to 20*0Sstevel@tonic-gatecode in a style with which they are comfortable. 21*0Sstevel@tonic-gate 22*0Sstevel@tonic-gatePerl B<borrows syntax> and concepts from many languages: awk, sed, C, 23*0Sstevel@tonic-gateBourne Shell, Smalltalk, Lisp and even English. Other 24*0Sstevel@tonic-gatelanguages have borrowed syntax from Perl, particularly its regular 25*0Sstevel@tonic-gateexpression extensions. So if you have programmed in another language 26*0Sstevel@tonic-gateyou will see familiar pieces in Perl. They often work the same, but 27*0Sstevel@tonic-gatesee L<perltrap> for information about how they differ. 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate=head2 Declarations 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gateThe only things you need to declare in Perl are report formats and 32*0Sstevel@tonic-gatesubroutines (and sometimes not even subroutines). A variable holds 33*0Sstevel@tonic-gatethe undefined value (C<undef>) until it has been assigned a defined 34*0Sstevel@tonic-gatevalue, which is anything other than C<undef>. When used as a number, 35*0Sstevel@tonic-gateC<undef> is treated as C<0>; when used as a string, it is treated as 36*0Sstevel@tonic-gatethe empty string, C<"">; and when used as a reference that isn't being 37*0Sstevel@tonic-gateassigned to, it is treated as an error. If you enable warnings, 38*0Sstevel@tonic-gateyou'll be notified of an uninitialized value whenever you treat 39*0Sstevel@tonic-gateC<undef> as a string or a number. Well, usually. Boolean contexts, 40*0Sstevel@tonic-gatesuch as: 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate my $a; 43*0Sstevel@tonic-gate if ($a) {} 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gateare exempt from warnings (because they care about truth rather than 46*0Sstevel@tonic-gatedefinedness). Operators such as C<++>, C<-->, C<+=>, 47*0Sstevel@tonic-gateC<-=>, and C<.=>, that operate on undefined left values such as: 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate my $a; 50*0Sstevel@tonic-gate $a++; 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gateare also always exempt from such warnings. 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gateA declaration can be put anywhere a statement can, but has no effect on 55*0Sstevel@tonic-gatethe execution of the primary sequence of statements--declarations all 56*0Sstevel@tonic-gatetake effect at compile time. Typically all the declarations are put at 57*0Sstevel@tonic-gatethe beginning or the end of the script. However, if you're using 58*0Sstevel@tonic-gatelexically-scoped private variables created with C<my()>, you'll 59*0Sstevel@tonic-gatehave to make sure 60*0Sstevel@tonic-gateyour format or subroutine definition is within the same block scope 61*0Sstevel@tonic-gateas the my if you expect to be able to access those private variables. 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gateDeclaring a subroutine allows a subroutine name to be used as if it were a 64*0Sstevel@tonic-gatelist operator from that point forward in the program. You can declare a 65*0Sstevel@tonic-gatesubroutine without defining it by saying C<sub name>, thus: 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate sub myname; 68*0Sstevel@tonic-gate $me = myname $0 or die "can't get myname"; 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gateNote that myname() functions as a list operator, not as a unary operator; 71*0Sstevel@tonic-gateso be careful to use C<or> instead of C<||> in this case. However, if 72*0Sstevel@tonic-gateyou were to declare the subroutine as C<sub myname ($)>, then 73*0Sstevel@tonic-gateC<myname> would function as a unary operator, so either C<or> or 74*0Sstevel@tonic-gateC<||> would work. 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gateSubroutines declarations can also be loaded up with the C<require> statement 77*0Sstevel@tonic-gateor both loaded and imported into your namespace with a C<use> statement. 78*0Sstevel@tonic-gateSee L<perlmod> for details on this. 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gateA statement sequence may contain declarations of lexically-scoped 81*0Sstevel@tonic-gatevariables, but apart from declaring a variable name, the declaration acts 82*0Sstevel@tonic-gatelike an ordinary statement, and is elaborated within the sequence of 83*0Sstevel@tonic-gatestatements as if it were an ordinary statement. That means it actually 84*0Sstevel@tonic-gatehas both compile-time and run-time effects. 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate=head2 Comments 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gateText from a C<"#"> character until the end of the line is a comment, 89*0Sstevel@tonic-gateand is ignored. Exceptions include C<"#"> inside a string or regular 90*0Sstevel@tonic-gateexpression. 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate=head2 Simple Statements 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gateThe only kind of simple statement is an expression evaluated for its 95*0Sstevel@tonic-gateside effects. Every simple statement must be terminated with a 96*0Sstevel@tonic-gatesemicolon, unless it is the final statement in a block, in which case 97*0Sstevel@tonic-gatethe semicolon is optional. (A semicolon is still encouraged if the 98*0Sstevel@tonic-gateblock takes up more than one line, because you may eventually add 99*0Sstevel@tonic-gateanother line.) Note that there are some operators like C<eval {}> and 100*0Sstevel@tonic-gateC<do {}> that look like compound statements, but aren't (they're just 101*0Sstevel@tonic-gateTERMs in an expression), and thus need an explicit termination if used 102*0Sstevel@tonic-gateas the last item in a statement. 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate=head2 Truth and Falsehood 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gateThe number 0, the strings C<'0'> and C<''>, the empty list C<()>, and 107*0Sstevel@tonic-gateC<undef> are all false in a boolean context. All other values are true. 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate=head2 Statement Modifiers 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gateAny simple statement may optionally be followed by a I<SINGLE> modifier, 112*0Sstevel@tonic-gatejust before the terminating semicolon (or block ending). The possible 113*0Sstevel@tonic-gatemodifiers are: 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate if EXPR 116*0Sstevel@tonic-gate unless EXPR 117*0Sstevel@tonic-gate while EXPR 118*0Sstevel@tonic-gate until EXPR 119*0Sstevel@tonic-gate foreach LIST 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gateThe C<EXPR> following the modifier is referred to as the "condition". 122*0Sstevel@tonic-gateIts truth or falsehood determines how the modifier will behave. 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gateC<if> executes the statement once I<if> and only if the condition is 125*0Sstevel@tonic-gatetrue. C<unless> is the opposite, it executes the statement I<unless> 126*0Sstevel@tonic-gatethe condition is true (i.e., if the condition is false). 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate print "Basset hounds got long ears" if length $ear >= 10; 129*0Sstevel@tonic-gate go_outside() and play() unless $is_raining; 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gateThe C<foreach> modifier is an iterator: it executes the statement once 132*0Sstevel@tonic-gatefor each item in the LIST (with C<$_> aliased to each item in turn). 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate print "Hello $_!\n" foreach qw(world Dolly nurse); 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gateC<while> repeats the statement I<while> the condition is true. 137*0Sstevel@tonic-gateC<until> does the opposite, it repeats the statement I<until> the 138*0Sstevel@tonic-gatecondition is true (or while the condition is false): 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate # Both of these count from 0 to 10. 141*0Sstevel@tonic-gate print $i++ while $i <= 10; 142*0Sstevel@tonic-gate print $j++ until $j > 10; 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gateThe C<while> and C<until> modifiers have the usual "C<while> loop" 145*0Sstevel@tonic-gatesemantics (conditional evaluated first), except when applied to a 146*0Sstevel@tonic-gateC<do>-BLOCK (or to the deprecated C<do>-SUBROUTINE statement), in 147*0Sstevel@tonic-gatewhich case the block executes once before the conditional is 148*0Sstevel@tonic-gateevaluated. This is so that you can write loops like: 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate do { 151*0Sstevel@tonic-gate $line = <STDIN>; 152*0Sstevel@tonic-gate ... 153*0Sstevel@tonic-gate } until $line eq ".\n"; 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gateSee L<perlfunc/do>. Note also that the loop control statements described 156*0Sstevel@tonic-gatelater will I<NOT> work in this construct, because modifiers don't take 157*0Sstevel@tonic-gateloop labels. Sorry. You can always put another block inside of it 158*0Sstevel@tonic-gate(for C<next>) or around it (for C<last>) to do that sort of thing. 159*0Sstevel@tonic-gateFor C<next>, just double the braces: 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate do {{ 162*0Sstevel@tonic-gate next if $x == $y; 163*0Sstevel@tonic-gate # do something here 164*0Sstevel@tonic-gate }} until $x++ > $z; 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gateFor C<last>, you have to be more elaborate: 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate LOOP: { 169*0Sstevel@tonic-gate do { 170*0Sstevel@tonic-gate last if $x = $y**2; 171*0Sstevel@tonic-gate # do something here 172*0Sstevel@tonic-gate } while $x++ <= $z; 173*0Sstevel@tonic-gate } 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gateB<NOTE:> The behaviour of a C<my> statement modified with a statement 176*0Sstevel@tonic-gatemodifier conditional or loop construct (e.g. C<my $x if ...>) is 177*0Sstevel@tonic-gateB<undefined>. The value of the C<my> variable may be C<undef>, any 178*0Sstevel@tonic-gatepreviously assigned value, or possibly anything else. Don't rely on 179*0Sstevel@tonic-gateit. Future versions of perl might do something different from the 180*0Sstevel@tonic-gateversion of perl you try it out on. Here be dragons. 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate=head2 Compound Statements 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gateIn Perl, a sequence of statements that defines a scope is called a block. 185*0Sstevel@tonic-gateSometimes a block is delimited by the file containing it (in the case 186*0Sstevel@tonic-gateof a required file, or the program as a whole), and sometimes a block 187*0Sstevel@tonic-gateis delimited by the extent of a string (in the case of an eval). 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gateBut generally, a block is delimited by curly brackets, also known as braces. 190*0Sstevel@tonic-gateWe will call this syntactic construct a BLOCK. 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gateThe following compound statements may be used to control flow: 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate if (EXPR) BLOCK 195*0Sstevel@tonic-gate if (EXPR) BLOCK else BLOCK 196*0Sstevel@tonic-gate if (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK 197*0Sstevel@tonic-gate LABEL while (EXPR) BLOCK 198*0Sstevel@tonic-gate LABEL while (EXPR) BLOCK continue BLOCK 199*0Sstevel@tonic-gate LABEL for (EXPR; EXPR; EXPR) BLOCK 200*0Sstevel@tonic-gate LABEL foreach VAR (LIST) BLOCK 201*0Sstevel@tonic-gate LABEL foreach VAR (LIST) BLOCK continue BLOCK 202*0Sstevel@tonic-gate LABEL BLOCK continue BLOCK 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gateNote that, unlike C and Pascal, these are defined in terms of BLOCKs, 205*0Sstevel@tonic-gatenot statements. This means that the curly brackets are I<required>--no 206*0Sstevel@tonic-gatedangling statements allowed. If you want to write conditionals without 207*0Sstevel@tonic-gatecurly brackets there are several other ways to do it. The following 208*0Sstevel@tonic-gateall do the same thing: 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate if (!open(FOO)) { die "Can't open $FOO: $!"; } 211*0Sstevel@tonic-gate die "Can't open $FOO: $!" unless open(FOO); 212*0Sstevel@tonic-gate open(FOO) or die "Can't open $FOO: $!"; # FOO or bust! 213*0Sstevel@tonic-gate open(FOO) ? 'hi mom' : die "Can't open $FOO: $!"; 214*0Sstevel@tonic-gate # a bit exotic, that last one 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gateThe C<if> statement is straightforward. Because BLOCKs are always 217*0Sstevel@tonic-gatebounded by curly brackets, there is never any ambiguity about which 218*0Sstevel@tonic-gateC<if> an C<else> goes with. If you use C<unless> in place of C<if>, 219*0Sstevel@tonic-gatethe sense of the test is reversed. 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gateThe C<while> statement executes the block as long as the expression is 222*0Sstevel@tonic-gatetrue (does not evaluate to the null string C<""> or C<0> or C<"0">). 223*0Sstevel@tonic-gateThe LABEL is optional, and if present, consists of an identifier followed 224*0Sstevel@tonic-gateby a colon. The LABEL identifies the loop for the loop control 225*0Sstevel@tonic-gatestatements C<next>, C<last>, and C<redo>. 226*0Sstevel@tonic-gateIf the LABEL is omitted, the loop control statement 227*0Sstevel@tonic-gaterefers to the innermost enclosing loop. This may include dynamically 228*0Sstevel@tonic-gatelooking back your call-stack at run time to find the LABEL. Such 229*0Sstevel@tonic-gatedesperate behavior triggers a warning if you use the C<use warnings> 230*0Sstevel@tonic-gatepragma or the B<-w> flag. 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gateIf there is a C<continue> BLOCK, it is always executed just before the 233*0Sstevel@tonic-gateconditional is about to be evaluated again. Thus it can be used to 234*0Sstevel@tonic-gateincrement a loop variable, even when the loop has been continued via 235*0Sstevel@tonic-gatethe C<next> statement. 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate=head2 Loop Control 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gateThe C<next> command starts the next iteration of the loop: 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate LINE: while (<STDIN>) { 242*0Sstevel@tonic-gate next LINE if /^#/; # discard comments 243*0Sstevel@tonic-gate ... 244*0Sstevel@tonic-gate } 245*0Sstevel@tonic-gate 246*0Sstevel@tonic-gateThe C<last> command immediately exits the loop in question. The 247*0Sstevel@tonic-gateC<continue> block, if any, is not executed: 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate LINE: while (<STDIN>) { 250*0Sstevel@tonic-gate last LINE if /^$/; # exit when done with header 251*0Sstevel@tonic-gate ... 252*0Sstevel@tonic-gate } 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gateThe C<redo> command restarts the loop block without evaluating the 255*0Sstevel@tonic-gateconditional again. The C<continue> block, if any, is I<not> executed. 256*0Sstevel@tonic-gateThis command is normally used by programs that want to lie to themselves 257*0Sstevel@tonic-gateabout what was just input. 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gateFor example, when processing a file like F</etc/termcap>. 260*0Sstevel@tonic-gateIf your input lines might end in backslashes to indicate continuation, you 261*0Sstevel@tonic-gatewant to skip ahead and get the next record. 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate while (<>) { 264*0Sstevel@tonic-gate chomp; 265*0Sstevel@tonic-gate if (s/\\$//) { 266*0Sstevel@tonic-gate $_ .= <>; 267*0Sstevel@tonic-gate redo unless eof(); 268*0Sstevel@tonic-gate } 269*0Sstevel@tonic-gate # now process $_ 270*0Sstevel@tonic-gate } 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gatewhich is Perl short-hand for the more explicitly written version: 273*0Sstevel@tonic-gate 274*0Sstevel@tonic-gate LINE: while (defined($line = <ARGV>)) { 275*0Sstevel@tonic-gate chomp($line); 276*0Sstevel@tonic-gate if ($line =~ s/\\$//) { 277*0Sstevel@tonic-gate $line .= <ARGV>; 278*0Sstevel@tonic-gate redo LINE unless eof(); # not eof(ARGV)! 279*0Sstevel@tonic-gate } 280*0Sstevel@tonic-gate # now process $line 281*0Sstevel@tonic-gate } 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gateNote that if there were a C<continue> block on the above code, it would 284*0Sstevel@tonic-gateget executed only on lines discarded by the regex (since redo skips the 285*0Sstevel@tonic-gatecontinue block). A continue block is often used to reset line counters 286*0Sstevel@tonic-gateor C<?pat?> one-time matches: 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate # inspired by :1,$g/fred/s//WILMA/ 289*0Sstevel@tonic-gate while (<>) { 290*0Sstevel@tonic-gate ?(fred)? && s//WILMA $1 WILMA/; 291*0Sstevel@tonic-gate ?(barney)? && s//BETTY $1 BETTY/; 292*0Sstevel@tonic-gate ?(homer)? && s//MARGE $1 MARGE/; 293*0Sstevel@tonic-gate } continue { 294*0Sstevel@tonic-gate print "$ARGV $.: $_"; 295*0Sstevel@tonic-gate close ARGV if eof(); # reset $. 296*0Sstevel@tonic-gate reset if eof(); # reset ?pat? 297*0Sstevel@tonic-gate } 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gateIf the word C<while> is replaced by the word C<until>, the sense of the 300*0Sstevel@tonic-gatetest is reversed, but the conditional is still tested before the first 301*0Sstevel@tonic-gateiteration. 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gateThe loop control statements don't work in an C<if> or C<unless>, since 304*0Sstevel@tonic-gatethey aren't loops. You can double the braces to make them such, though. 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate if (/pattern/) {{ 307*0Sstevel@tonic-gate last if /fred/; 308*0Sstevel@tonic-gate next if /barney/; # same effect as "last", but doesn't document as well 309*0Sstevel@tonic-gate # do something here 310*0Sstevel@tonic-gate }} 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gateThis is caused by the fact that a block by itself acts as a loop that 313*0Sstevel@tonic-gateexecutes once, see L<"Basic BLOCKs and Switch Statements">. 314*0Sstevel@tonic-gate 315*0Sstevel@tonic-gateThe form C<while/if BLOCK BLOCK>, available in Perl 4, is no longer 316*0Sstevel@tonic-gateavailable. Replace any occurrence of C<if BLOCK> by C<if (do BLOCK)>. 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate=head2 For Loops 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gatePerl's C-style C<for> loop works like the corresponding C<while> loop; 321*0Sstevel@tonic-gatethat means that this: 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate for ($i = 1; $i < 10; $i++) { 324*0Sstevel@tonic-gate ... 325*0Sstevel@tonic-gate } 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gateis the same as this: 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate $i = 1; 330*0Sstevel@tonic-gate while ($i < 10) { 331*0Sstevel@tonic-gate ... 332*0Sstevel@tonic-gate } continue { 333*0Sstevel@tonic-gate $i++; 334*0Sstevel@tonic-gate } 335*0Sstevel@tonic-gate 336*0Sstevel@tonic-gateThere is one minor difference: if variables are declared with C<my> 337*0Sstevel@tonic-gatein the initialization section of the C<for>, the lexical scope of 338*0Sstevel@tonic-gatethose variables is exactly the C<for> loop (the body of the loop 339*0Sstevel@tonic-gateand the control sections). 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gateBesides the normal array index looping, C<for> can lend itself 342*0Sstevel@tonic-gateto many other interesting applications. Here's one that avoids the 343*0Sstevel@tonic-gateproblem you get into if you explicitly test for end-of-file on 344*0Sstevel@tonic-gatean interactive file descriptor causing your program to appear to 345*0Sstevel@tonic-gatehang. 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate $on_a_tty = -t STDIN && -t STDOUT; 348*0Sstevel@tonic-gate sub prompt { print "yes? " if $on_a_tty } 349*0Sstevel@tonic-gate for ( prompt(); <STDIN>; prompt() ) { 350*0Sstevel@tonic-gate # do something 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gateUsing C<readline> (or the operator form, C<< <EXPR> >>) as the 354*0Sstevel@tonic-gateconditional of a C<for> loop is shorthand for the following. This 355*0Sstevel@tonic-gatebehaviour is the same as a C<while> loop conditional. 356*0Sstevel@tonic-gate 357*0Sstevel@tonic-gate for ( prompt(); defined( $_ = <STDIN> ); prompt() ) { 358*0Sstevel@tonic-gate # do something 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate=head2 Foreach Loops 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gateThe C<foreach> loop iterates over a normal list value and sets the 364*0Sstevel@tonic-gatevariable VAR to be each element of the list in turn. If the variable 365*0Sstevel@tonic-gateis preceded with the keyword C<my>, then it is lexically scoped, and 366*0Sstevel@tonic-gateis therefore visible only within the loop. Otherwise, the variable is 367*0Sstevel@tonic-gateimplicitly local to the loop and regains its former value upon exiting 368*0Sstevel@tonic-gatethe loop. If the variable was previously declared with C<my>, it uses 369*0Sstevel@tonic-gatethat variable instead of the global one, but it's still localized to 370*0Sstevel@tonic-gatethe loop. This implicit localisation occurs I<only> in a C<foreach> 371*0Sstevel@tonic-gateloop. 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gateThe C<foreach> keyword is actually a synonym for the C<for> keyword, so 374*0Sstevel@tonic-gateyou can use C<foreach> for readability or C<for> for brevity. (Or because 375*0Sstevel@tonic-gatethe Bourne shell is more familiar to you than I<csh>, so writing C<for> 376*0Sstevel@tonic-gatecomes more naturally.) If VAR is omitted, C<$_> is set to each value. 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gateIf any element of LIST is an lvalue, you can modify it by modifying 379*0Sstevel@tonic-gateVAR inside the loop. Conversely, if any element of LIST is NOT an 380*0Sstevel@tonic-gatelvalue, any attempt to modify that element will fail. In other words, 381*0Sstevel@tonic-gatethe C<foreach> loop index variable is an implicit alias for each item 382*0Sstevel@tonic-gatein the list that you're looping over. 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gateIf any part of LIST is an array, C<foreach> will get very confused if 385*0Sstevel@tonic-gateyou add or remove elements within the loop body, for example with 386*0Sstevel@tonic-gateC<splice>. So don't do that. 387*0Sstevel@tonic-gate 388*0Sstevel@tonic-gateC<foreach> probably won't do what you expect if VAR is a tied or other 389*0Sstevel@tonic-gatespecial variable. Don't do that either. 390*0Sstevel@tonic-gate 391*0Sstevel@tonic-gateExamples: 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate for (@ary) { s/foo/bar/ } 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate for my $elem (@elements) { 396*0Sstevel@tonic-gate $elem *= 2; 397*0Sstevel@tonic-gate } 398*0Sstevel@tonic-gate 399*0Sstevel@tonic-gate for $count (10,9,8,7,6,5,4,3,2,1,'BOOM') { 400*0Sstevel@tonic-gate print $count, "\n"; sleep(1); 401*0Sstevel@tonic-gate } 402*0Sstevel@tonic-gate 403*0Sstevel@tonic-gate for (1..15) { print "Merry Christmas\n"; } 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate foreach $item (split(/:[\\\n:]*/, $ENV{TERMCAP})) { 406*0Sstevel@tonic-gate print "Item: $item\n"; 407*0Sstevel@tonic-gate } 408*0Sstevel@tonic-gate 409*0Sstevel@tonic-gateHere's how a C programmer might code up a particular algorithm in Perl: 410*0Sstevel@tonic-gate 411*0Sstevel@tonic-gate for (my $i = 0; $i < @ary1; $i++) { 412*0Sstevel@tonic-gate for (my $j = 0; $j < @ary2; $j++) { 413*0Sstevel@tonic-gate if ($ary1[$i] > $ary2[$j]) { 414*0Sstevel@tonic-gate last; # can't go to outer :-( 415*0Sstevel@tonic-gate } 416*0Sstevel@tonic-gate $ary1[$i] += $ary2[$j]; 417*0Sstevel@tonic-gate } 418*0Sstevel@tonic-gate # this is where that last takes me 419*0Sstevel@tonic-gate } 420*0Sstevel@tonic-gate 421*0Sstevel@tonic-gateWhereas here's how a Perl programmer more comfortable with the idiom might 422*0Sstevel@tonic-gatedo it: 423*0Sstevel@tonic-gate 424*0Sstevel@tonic-gate OUTER: for my $wid (@ary1) { 425*0Sstevel@tonic-gate INNER: for my $jet (@ary2) { 426*0Sstevel@tonic-gate next OUTER if $wid > $jet; 427*0Sstevel@tonic-gate $wid += $jet; 428*0Sstevel@tonic-gate } 429*0Sstevel@tonic-gate } 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gateSee how much easier this is? It's cleaner, safer, and faster. It's 432*0Sstevel@tonic-gatecleaner because it's less noisy. It's safer because if code gets added 433*0Sstevel@tonic-gatebetween the inner and outer loops later on, the new code won't be 434*0Sstevel@tonic-gateaccidentally executed. The C<next> explicitly iterates the other loop 435*0Sstevel@tonic-gaterather than merely terminating the inner one. And it's faster because 436*0Sstevel@tonic-gatePerl executes a C<foreach> statement more rapidly than it would the 437*0Sstevel@tonic-gateequivalent C<for> loop. 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate=head2 Basic BLOCKs and Switch Statements 440*0Sstevel@tonic-gate 441*0Sstevel@tonic-gateA BLOCK by itself (labeled or not) is semantically equivalent to a 442*0Sstevel@tonic-gateloop that executes once. Thus you can use any of the loop control 443*0Sstevel@tonic-gatestatements in it to leave or restart the block. (Note that this is 444*0Sstevel@tonic-gateI<NOT> true in C<eval{}>, C<sub{}>, or contrary to popular belief 445*0Sstevel@tonic-gateC<do{}> blocks, which do I<NOT> count as loops.) The C<continue> 446*0Sstevel@tonic-gateblock is optional. 447*0Sstevel@tonic-gate 448*0Sstevel@tonic-gateThe BLOCK construct is particularly nice for doing case 449*0Sstevel@tonic-gatestructures. 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate SWITCH: { 452*0Sstevel@tonic-gate if (/^abc/) { $abc = 1; last SWITCH; } 453*0Sstevel@tonic-gate if (/^def/) { $def = 1; last SWITCH; } 454*0Sstevel@tonic-gate if (/^xyz/) { $xyz = 1; last SWITCH; } 455*0Sstevel@tonic-gate $nothing = 1; 456*0Sstevel@tonic-gate } 457*0Sstevel@tonic-gate 458*0Sstevel@tonic-gateThere is no official C<switch> statement in Perl, because there are 459*0Sstevel@tonic-gatealready several ways to write the equivalent. 460*0Sstevel@tonic-gate 461*0Sstevel@tonic-gateHowever, starting from Perl 5.8 to get switch and case one can use 462*0Sstevel@tonic-gatethe Switch extension and say: 463*0Sstevel@tonic-gate 464*0Sstevel@tonic-gate use Switch; 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gateafter which one has switch and case. It is not as fast as it could be 467*0Sstevel@tonic-gatebecause it's not really part of the language (it's done using source 468*0Sstevel@tonic-gatefilters) but it is available, and it's very flexible. 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gateIn addition to the above BLOCK construct, you could write 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate SWITCH: { 473*0Sstevel@tonic-gate $abc = 1, last SWITCH if /^abc/; 474*0Sstevel@tonic-gate $def = 1, last SWITCH if /^def/; 475*0Sstevel@tonic-gate $xyz = 1, last SWITCH if /^xyz/; 476*0Sstevel@tonic-gate $nothing = 1; 477*0Sstevel@tonic-gate } 478*0Sstevel@tonic-gate 479*0Sstevel@tonic-gate(That's actually not as strange as it looks once you realize that you can 480*0Sstevel@tonic-gateuse loop control "operators" within an expression. That's just the binary 481*0Sstevel@tonic-gatecomma operator in scalar context. See L<perlop/"Comma Operator">.) 482*0Sstevel@tonic-gate 483*0Sstevel@tonic-gateor 484*0Sstevel@tonic-gate 485*0Sstevel@tonic-gate SWITCH: { 486*0Sstevel@tonic-gate /^abc/ && do { $abc = 1; last SWITCH; }; 487*0Sstevel@tonic-gate /^def/ && do { $def = 1; last SWITCH; }; 488*0Sstevel@tonic-gate /^xyz/ && do { $xyz = 1; last SWITCH; }; 489*0Sstevel@tonic-gate $nothing = 1; 490*0Sstevel@tonic-gate } 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gateor formatted so it stands out more as a "proper" C<switch> statement: 493*0Sstevel@tonic-gate 494*0Sstevel@tonic-gate SWITCH: { 495*0Sstevel@tonic-gate /^abc/ && do { 496*0Sstevel@tonic-gate $abc = 1; 497*0Sstevel@tonic-gate last SWITCH; 498*0Sstevel@tonic-gate }; 499*0Sstevel@tonic-gate 500*0Sstevel@tonic-gate /^def/ && do { 501*0Sstevel@tonic-gate $def = 1; 502*0Sstevel@tonic-gate last SWITCH; 503*0Sstevel@tonic-gate }; 504*0Sstevel@tonic-gate 505*0Sstevel@tonic-gate /^xyz/ && do { 506*0Sstevel@tonic-gate $xyz = 1; 507*0Sstevel@tonic-gate last SWITCH; 508*0Sstevel@tonic-gate }; 509*0Sstevel@tonic-gate $nothing = 1; 510*0Sstevel@tonic-gate } 511*0Sstevel@tonic-gate 512*0Sstevel@tonic-gateor 513*0Sstevel@tonic-gate 514*0Sstevel@tonic-gate SWITCH: { 515*0Sstevel@tonic-gate /^abc/ and $abc = 1, last SWITCH; 516*0Sstevel@tonic-gate /^def/ and $def = 1, last SWITCH; 517*0Sstevel@tonic-gate /^xyz/ and $xyz = 1, last SWITCH; 518*0Sstevel@tonic-gate $nothing = 1; 519*0Sstevel@tonic-gate } 520*0Sstevel@tonic-gate 521*0Sstevel@tonic-gateor even, horrors, 522*0Sstevel@tonic-gate 523*0Sstevel@tonic-gate if (/^abc/) 524*0Sstevel@tonic-gate { $abc = 1 } 525*0Sstevel@tonic-gate elsif (/^def/) 526*0Sstevel@tonic-gate { $def = 1 } 527*0Sstevel@tonic-gate elsif (/^xyz/) 528*0Sstevel@tonic-gate { $xyz = 1 } 529*0Sstevel@tonic-gate else 530*0Sstevel@tonic-gate { $nothing = 1 } 531*0Sstevel@tonic-gate 532*0Sstevel@tonic-gateA common idiom for a C<switch> statement is to use C<foreach>'s aliasing to make 533*0Sstevel@tonic-gatea temporary assignment to C<$_> for convenient matching: 534*0Sstevel@tonic-gate 535*0Sstevel@tonic-gate SWITCH: for ($where) { 536*0Sstevel@tonic-gate /In Card Names/ && do { push @flags, '-e'; last; }; 537*0Sstevel@tonic-gate /Anywhere/ && do { push @flags, '-h'; last; }; 538*0Sstevel@tonic-gate /In Rulings/ && do { last; }; 539*0Sstevel@tonic-gate die "unknown value for form variable where: `$where'"; 540*0Sstevel@tonic-gate } 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gateAnother interesting approach to a switch statement is arrange 543*0Sstevel@tonic-gatefor a C<do> block to return the proper value: 544*0Sstevel@tonic-gate 545*0Sstevel@tonic-gate $amode = do { 546*0Sstevel@tonic-gate if ($flag & O_RDONLY) { "r" } # XXX: isn't this 0? 547*0Sstevel@tonic-gate elsif ($flag & O_WRONLY) { ($flag & O_APPEND) ? "a" : "w" } 548*0Sstevel@tonic-gate elsif ($flag & O_RDWR) { 549*0Sstevel@tonic-gate if ($flag & O_CREAT) { "w+" } 550*0Sstevel@tonic-gate else { ($flag & O_APPEND) ? "a+" : "r+" } 551*0Sstevel@tonic-gate } 552*0Sstevel@tonic-gate }; 553*0Sstevel@tonic-gate 554*0Sstevel@tonic-gateOr 555*0Sstevel@tonic-gate 556*0Sstevel@tonic-gate print do { 557*0Sstevel@tonic-gate ($flags & O_WRONLY) ? "write-only" : 558*0Sstevel@tonic-gate ($flags & O_RDWR) ? "read-write" : 559*0Sstevel@tonic-gate "read-only"; 560*0Sstevel@tonic-gate }; 561*0Sstevel@tonic-gate 562*0Sstevel@tonic-gateOr if you are certain that all the C<&&> clauses are true, you can use 563*0Sstevel@tonic-gatesomething like this, which "switches" on the value of the 564*0Sstevel@tonic-gateC<HTTP_USER_AGENT> environment variable. 565*0Sstevel@tonic-gate 566*0Sstevel@tonic-gate #!/usr/bin/perl 567*0Sstevel@tonic-gate # pick out jargon file page based on browser 568*0Sstevel@tonic-gate $dir = 'http://www.wins.uva.nl/~mes/jargon'; 569*0Sstevel@tonic-gate for ($ENV{HTTP_USER_AGENT}) { 570*0Sstevel@tonic-gate $page = /Mac/ && 'm/Macintrash.html' 571*0Sstevel@tonic-gate || /Win(dows )?NT/ && 'e/evilandrude.html' 572*0Sstevel@tonic-gate || /Win|MSIE|WebTV/ && 'm/MicroslothWindows.html' 573*0Sstevel@tonic-gate || /Linux/ && 'l/Linux.html' 574*0Sstevel@tonic-gate || /HP-UX/ && 'h/HP-SUX.html' 575*0Sstevel@tonic-gate || /SunOS/ && 's/ScumOS.html' 576*0Sstevel@tonic-gate || 'a/AppendixB.html'; 577*0Sstevel@tonic-gate } 578*0Sstevel@tonic-gate print "Location: $dir/$page\015\012\015\012"; 579*0Sstevel@tonic-gate 580*0Sstevel@tonic-gateThat kind of switch statement only works when you know the C<&&> clauses 581*0Sstevel@tonic-gatewill be true. If you don't, the previous C<?:> example should be used. 582*0Sstevel@tonic-gate 583*0Sstevel@tonic-gateYou might also consider writing a hash of subroutine references 584*0Sstevel@tonic-gateinstead of synthesizing a C<switch> statement. 585*0Sstevel@tonic-gate 586*0Sstevel@tonic-gate=head2 Goto 587*0Sstevel@tonic-gate 588*0Sstevel@tonic-gateAlthough not for the faint of heart, Perl does support a C<goto> 589*0Sstevel@tonic-gatestatement. There are three forms: C<goto>-LABEL, C<goto>-EXPR, and 590*0Sstevel@tonic-gateC<goto>-&NAME. A loop's LABEL is not actually a valid target for 591*0Sstevel@tonic-gatea C<goto>; it's just the name of the loop. 592*0Sstevel@tonic-gate 593*0Sstevel@tonic-gateThe C<goto>-LABEL form finds the statement labeled with LABEL and resumes 594*0Sstevel@tonic-gateexecution there. It may not be used to go into any construct that 595*0Sstevel@tonic-gaterequires initialization, such as a subroutine or a C<foreach> loop. It 596*0Sstevel@tonic-gatealso can't be used to go into a construct that is optimized away. It 597*0Sstevel@tonic-gatecan be used to go almost anywhere else within the dynamic scope, 598*0Sstevel@tonic-gateincluding out of subroutines, but it's usually better to use some other 599*0Sstevel@tonic-gateconstruct such as C<last> or C<die>. The author of Perl has never felt the 600*0Sstevel@tonic-gateneed to use this form of C<goto> (in Perl, that is--C is another matter). 601*0Sstevel@tonic-gate 602*0Sstevel@tonic-gateThe C<goto>-EXPR form expects a label name, whose scope will be resolved 603*0Sstevel@tonic-gatedynamically. This allows for computed C<goto>s per FORTRAN, but isn't 604*0Sstevel@tonic-gatenecessarily recommended if you're optimizing for maintainability: 605*0Sstevel@tonic-gate 606*0Sstevel@tonic-gate goto(("FOO", "BAR", "GLARCH")[$i]); 607*0Sstevel@tonic-gate 608*0Sstevel@tonic-gateThe C<goto>-&NAME form is highly magical, and substitutes a call to the 609*0Sstevel@tonic-gatenamed subroutine for the currently running subroutine. This is used by 610*0Sstevel@tonic-gateC<AUTOLOAD()> subroutines that wish to load another subroutine and then 611*0Sstevel@tonic-gatepretend that the other subroutine had been called in the first place 612*0Sstevel@tonic-gate(except that any modifications to C<@_> in the current subroutine are 613*0Sstevel@tonic-gatepropagated to the other subroutine.) After the C<goto>, not even C<caller()> 614*0Sstevel@tonic-gatewill be able to tell that this routine was called first. 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gateIn almost all cases like this, it's usually a far, far better idea to use the 617*0Sstevel@tonic-gatestructured control flow mechanisms of C<next>, C<last>, or C<redo> instead of 618*0Sstevel@tonic-gateresorting to a C<goto>. For certain applications, the catch and throw pair of 619*0Sstevel@tonic-gateC<eval{}> and die() for exception processing can also be a prudent approach. 620*0Sstevel@tonic-gate 621*0Sstevel@tonic-gate=head2 PODs: Embedded Documentation 622*0Sstevel@tonic-gate 623*0Sstevel@tonic-gatePerl has a mechanism for intermixing documentation with source code. 624*0Sstevel@tonic-gateWhile it's expecting the beginning of a new statement, if the compiler 625*0Sstevel@tonic-gateencounters a line that begins with an equal sign and a word, like this 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate =head1 Here There Be Pods! 628*0Sstevel@tonic-gate 629*0Sstevel@tonic-gateThen that text and all remaining text up through and including a line 630*0Sstevel@tonic-gatebeginning with C<=cut> will be ignored. The format of the intervening 631*0Sstevel@tonic-gatetext is described in L<perlpod>. 632*0Sstevel@tonic-gate 633*0Sstevel@tonic-gateThis allows you to intermix your source code 634*0Sstevel@tonic-gateand your documentation text freely, as in 635*0Sstevel@tonic-gate 636*0Sstevel@tonic-gate =item snazzle($) 637*0Sstevel@tonic-gate 638*0Sstevel@tonic-gate The snazzle() function will behave in the most spectacular 639*0Sstevel@tonic-gate form that you can possibly imagine, not even excepting 640*0Sstevel@tonic-gate cybernetic pyrotechnics. 641*0Sstevel@tonic-gate 642*0Sstevel@tonic-gate =cut back to the compiler, nuff of this pod stuff! 643*0Sstevel@tonic-gate 644*0Sstevel@tonic-gate sub snazzle($) { 645*0Sstevel@tonic-gate my $thingie = shift; 646*0Sstevel@tonic-gate ......... 647*0Sstevel@tonic-gate } 648*0Sstevel@tonic-gate 649*0Sstevel@tonic-gateNote that pod translators should look at only paragraphs beginning 650*0Sstevel@tonic-gatewith a pod directive (it makes parsing easier), whereas the compiler 651*0Sstevel@tonic-gateactually knows to look for pod escapes even in the middle of a 652*0Sstevel@tonic-gateparagraph. This means that the following secret stuff will be 653*0Sstevel@tonic-gateignored by both the compiler and the translators. 654*0Sstevel@tonic-gate 655*0Sstevel@tonic-gate $a=3; 656*0Sstevel@tonic-gate =secret stuff 657*0Sstevel@tonic-gate warn "Neither POD nor CODE!?" 658*0Sstevel@tonic-gate =cut back 659*0Sstevel@tonic-gate print "got $a\n"; 660*0Sstevel@tonic-gate 661*0Sstevel@tonic-gateYou probably shouldn't rely upon the C<warn()> being podded out forever. 662*0Sstevel@tonic-gateNot all pod translators are well-behaved in this regard, and perhaps 663*0Sstevel@tonic-gatethe compiler will become pickier. 664*0Sstevel@tonic-gate 665*0Sstevel@tonic-gateOne may also use pod directives to quickly comment out a section 666*0Sstevel@tonic-gateof code. 667*0Sstevel@tonic-gate 668*0Sstevel@tonic-gate=head2 Plain Old Comments (Not!) 669*0Sstevel@tonic-gate 670*0Sstevel@tonic-gatePerl can process line directives, much like the C preprocessor. Using 671*0Sstevel@tonic-gatethis, one can control Perl's idea of filenames and line numbers in 672*0Sstevel@tonic-gateerror or warning messages (especially for strings that are processed 673*0Sstevel@tonic-gatewith C<eval()>). The syntax for this mechanism is the same as for most 674*0Sstevel@tonic-gateC preprocessors: it matches the regular expression 675*0Sstevel@tonic-gate 676*0Sstevel@tonic-gate # example: '# line 42 "new_filename.plx"' 677*0Sstevel@tonic-gate /^\# \s* 678*0Sstevel@tonic-gate line \s+ (\d+) \s* 679*0Sstevel@tonic-gate (?:\s("?)([^"]+)\2)? \s* 680*0Sstevel@tonic-gate $/x 681*0Sstevel@tonic-gate 682*0Sstevel@tonic-gatewith C<$1> being the line number for the next line, and C<$3> being 683*0Sstevel@tonic-gatethe optional filename (specified with or without quotes). 684*0Sstevel@tonic-gate 685*0Sstevel@tonic-gateThere is a fairly obvious gotcha included with the line directive: 686*0Sstevel@tonic-gateDebuggers and profilers will only show the last source line to appear 687*0Sstevel@tonic-gateat a particular line number in a given file. Care should be taken not 688*0Sstevel@tonic-gateto cause line number collisions in code you'd like to debug later. 689*0Sstevel@tonic-gate 690*0Sstevel@tonic-gateHere are some examples that you should be able to type into your command 691*0Sstevel@tonic-gateshell: 692*0Sstevel@tonic-gate 693*0Sstevel@tonic-gate % perl 694*0Sstevel@tonic-gate # line 200 "bzzzt" 695*0Sstevel@tonic-gate # the `#' on the previous line must be the first char on line 696*0Sstevel@tonic-gate die 'foo'; 697*0Sstevel@tonic-gate __END__ 698*0Sstevel@tonic-gate foo at bzzzt line 201. 699*0Sstevel@tonic-gate 700*0Sstevel@tonic-gate % perl 701*0Sstevel@tonic-gate # line 200 "bzzzt" 702*0Sstevel@tonic-gate eval qq[\n#line 2001 ""\ndie 'foo']; print $@; 703*0Sstevel@tonic-gate __END__ 704*0Sstevel@tonic-gate foo at - line 2001. 705*0Sstevel@tonic-gate 706*0Sstevel@tonic-gate % perl 707*0Sstevel@tonic-gate eval qq[\n#line 200 "foo bar"\ndie 'foo']; print $@; 708*0Sstevel@tonic-gate __END__ 709*0Sstevel@tonic-gate foo at foo bar line 200. 710*0Sstevel@tonic-gate 711*0Sstevel@tonic-gate % perl 712*0Sstevel@tonic-gate # line 345 "goop" 713*0Sstevel@tonic-gate eval "\n#line " . __LINE__ . ' "' . __FILE__ ."\"\ndie 'foo'"; 714*0Sstevel@tonic-gate print $@; 715*0Sstevel@tonic-gate __END__ 716*0Sstevel@tonic-gate foo at goop line 345. 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate=cut 719