Advanced Perl Programming by Sriram Srinivasan This errata page lists errors outstanding in the most recent printing, 12/97. If you have technical questions or error reports, you can send them to booktech@oreilly.com. Please specify the printing date of your copy. This page was last modified on September 14, 1998. Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification Confirmed errors: (xi) line 1: There is an extra space between "two" and "goals" (xiv) para. -1, line 2: "Guido Van Rossum" should be "Guido van Rossum" and there should be a thinspace between the final backslash of the URL and the close paren (xiv) line -2: ")." should be ".)" (xv) bullet item 2: need a comma after "The Perl interpreter" (xxiii) Acknowledgments: next-to-last para.: need comma after "encouraging words" (xxiii) Move the last but one para ("To all my friends ...") to the end, and say, "Finally, to all my friends, ...." (2) para 4, line 4: change "procedures" to "functions". (2) para. 5, line 1: change "As we saw earlier, you" to "You" (3) line 21: "...we'll the study the..." should be "...we'll study the..." {5} last code example, line 4: "[$i]" should be "[1]" (9) Both pieces of code: The lines "sub AddArrays" and "sub GetNextLine" should not be indented. Also, the 8-space tabs should be 4-space tabs. (10) First code example: Change comment to: # Call GetNextLine 100 times, and time it. (11) Second code example from below.: Change comment in 3rd line to: # reference to a reference to $a's value (14) First para. after heading "Final Shortcut ...": Change "identical" to "equivalent" (21) line 5 under the header "Tcl": replace "such as Perl's symbolic references" with "equivalent to Perl's symbolic references" (26) the dot inside the formula should be a raised to be a centered dot (26) line 3 in Example 2-2: my ($r_product); # Returing product by reference should read my ($r_product); # Returning product by reference (27) Whole page: Badly formatted arrows after "$r_mat" {29} first Code after "Representation": The ID-Nr. of "Garibaldi" is wrong, this is the ID of "E. F. Schumacher", according to P 28 {31} example 2-4, line 12 for $j ($i .. $#{$rl_courses}) { should be for $j ($i+1 .. $#{$rl_courses}) { {33} First line of code: ... die "Could not open database: $:"; "$:" should be "$!" (37) Resources: #1 should say: 1. The FMTEYEWTK series (Far More Than Everything You've Ever Wanted to Know). Tom Christiansen. Available at http://www.perl.com/CPAN-local/doc/FMTEYEWTK/index.html (40) next-to-last para.: "A" is in CW when it should be in Roman (41) line 1: "create new variable" should be "create a new variable" {47} The sample code fragment contains two comments erroneously refering to '$&rs()'. The dollar sign and ampersand should be exchanged. (49) para. 1, "The simple answer to this solution is..." should be "The simple solution to this problem is..." (50) "A #include" should read "An #include" (line 1) {53} line 7: $rsub->(10); should be $rs->(10); (55) para after first code block.: "INT is a reserved string and" should be "INT is a special string that" (55) Last para, line 5: Change "crash the system" to "crash the program" (56) "Expression Plotting" should be a B-Head (with "Plotting" capitalized), not a C (56) 2nd line before Closures: should be "...higher-order procedure;" (not "procedures;") (56) 2nd line after Closures: should be: "...any other way of passing subroutine" (not "other ways") (57) para. 2, line -2: the quotes around "$greeting" are mismatched {61} top of page: Not really a bug, but a matter of style (Unnecessarily using global variables) $rs = sub { could be: my $rs = sub { {62} Example 4-4: two anonymous subroutines are commented as being "Even number printer"s. The second should be commented "Odd number printer." [63] example before heading "Closures Versus Objects": "$random_iter1()" and "$random_iter2()" should be "&$random_iter1()" and "&$random_iter2()" respectively {66} First line: 48K should be 32K. (69) The first piece of code: Quote missing at end of comment "Illegal division ...." (69) Last para, last line: "eval" should be in Courier. (75) line 1: the typeface of the first slash in "/$pat/" should be changed from body text to code. {75} 2nd para from bottom: If @patterns contains the three strings "^abc", "ghi", "efg$", should be: If @patterns contains the three strings "^foo", "bar$", "ghi", (To match the code following this line) {88} under "Load Path": "Perl first looks for the file given to use or require in the current directory and then looks up the @INC built-in array to search the include paths." should be: "Perl looks for the file given to use or require in the list of directories specified in the built-in array, @INC. {89} Last code block: "Create a variable subroutine and subroutine..." should be "Create a variable and a subroutine..." (91) Second para: "The BankAccount class can be" should be "The BankAccount package can be" {91} under "Importing Symbols", near the end of the section: "If the module uses @EXPORT instead of @EXPORT_OK, the user gets all the exported symbols, regardless of whether they were mentioned in the import list or not." should be: "If the module uses @EXPORT instead of @EXPORT_OK, the user gets all the exported symbols by default, unless the import list specifies one or more symbols" (92) The line before Example 6-1, "Example 6-1 shows one way to do write this subroutine." should read: "Example 6-1 shows one way to write this subroutine." (93) last line: "The double colon gets translated to a filename" should be "The double colon gets translated to a pathname" (94) Para after first code block: "Test::func" should be typeset in Courier. (100) Line 3: "Nicklaus" should be "Niklaus" (103) 5th line: "Not" should be "Note" (103) paragraph after first code block: "of the an object" should be "of a class" (106) Para after second code block: "it is the Regular-Employee" should be "it is RegularEmployee" {108} First code line: "$record" should be "$details" (114) "Can (function name)" has the open paren. in code and the close paren. in body text; the situation is reversed at the top of page 115. All the parens should be in code format. (116) Last para: "design is to use case analysis" should be "design is to use Use Case Analysis" (117) figure 7-1: "Moniter" should be "Monitor" {118} line -14 (from the bottom) of the page reads : $obj->{_price} - $obj->_rebate} it should read : $obj->{_price} - $obj->{_rebate} (119) line 2: "CDROM" should be bold {120} para about Tcl, last sentence: "incr Tcl" should be "[incr Tcl]" (120) 3rd line from bottom of para. about Tcl, the brackets around "incr Tcl" are mismatched and ought to both be CW {125} #2: line -2 of code: $r_employee->position... should be $emp->position... {126} "'J'Joe'" should be "'Joe'" {127} 2nd line under figure: "@free" should be "@_free" {127} next to last line on page: "@color" should be "@_color" {128} First line of text after code: "@_ATTRIBUTES" should be "@_ATTRIBUTES_" {129} First line after code (at top of page): $$_[0] should not be split across lines. {130} Code at top of page: second line messed up. It should read: # Or, $obj->set_attributes (['age', 'name'], [23, "sriram"]) sub set_attributes { [131] line 8 of first code example: local(*attributes) = *{"${pkg}::_ATTRIBUTES_"}; should be local (@attributes) = get_attribute_names($pkg); (134) line 7 in the second code example reads # Strip it off its leading package name... It should read: # Strip off its leading package name... (139) para. -3, line 2: the -> should be in CW font {141} last line: "the Win32::Timer call" should be "the Win32::Timer package" (141) 4th line from the bottom: "Time::HiRes" should be in CW font {144} First para after code: This para is redundant (although correct in intention) because STORE has not been implemented in the preceding example. {146} Table 9-4, column 1: The line print FH "I do"; # No comma after FH should not be wrapped. (This is probably impossible to fix with our current table format. -efm) (154) para. 1, line 4, "in a slightly greater detail": delete "a" (154) Serialization item, parenthetical at end: "(making the structures cyclic ...)" should be "(possibly making the structures cyclic ...)" (159) Para after "Record-Oriented Approach": "DBM is a disk-based hash table" should be "DBM is a disk-based hash table library" {160} line 3 of first code example, and line 2 of second code example: "Fcntl" should be "fcntl" (162) Second para after first code block: "$DBI::err" and "$DBI::errstr" should be typeset in Courier. {162} Last piece of code: $sth = $dbh->prepare('insert into emptable (name, age) values (? , ?)';); should be $sth = $dbh->prepare('insert into emptable (id, name, age) values (?, ? , ?)';); (166) line 2: "select" should be in CW font with no italics (169) Page header: The page header just reads "f". {170} First footnote: "select clause" should be "select command" {171} Code after figure 11-1, line 5 and 9: @ATTRIBUTES = qw(....); should be attributes qw(....); {171} At the bottom, it says that emfile.cfg looks like: [Employee] attributes = _id, name, age, ... Well, it doesn't. It looks like this: %g_attr_names = ( "Employee" => [qw(name age)] "Department" => [qw(name address)] ); The author says: It is a mistake. My intention was (and is) to create a configuration file parser that would create the structure %g_attr_names. I ran out of time at the end and couldn't create this parser. So, I took the easy way out and simply put this snippet of code in the "configuration file" and sourced it, instead of parsing it. At that time, my focus was on getting the main adapter to work right, and not how it handled the parsing. (175) 3rd line from bottom: Change "get/set_attributes" to "{get,set}_attributes" for consistency. (180) 1st para. under "Storing objects": "flush" should be "flush()" (181) 3rd para, last line: "Retrieving Objects" should be a heading; it is incorrectly part of the para body. (184) Last code block: subroutine name "store" should be typeset in bold. (186) Last code block: subroutine name "retrieve_where" should be typeset in bold. (192) First para, line 2: "LocalHost" and "LocalPort" should be typeset in Courier (193) code line 4: remove extra comma after 'tcp': ... Proto => 'tcp', should be ... Proto => 'tcp' {193} code line 9, after print $sock "Msg $_ : How are you?\n"; insert $sock->flush(); {193} Section "Sender", last line: "sending ports" should be "sending sockets" (194) Fourth para: Change "a specified socket" to "any socket" {194} #3: "Make these calls nonblocking" should be "Make these sockets nonblocking" {194} line 10 of code: "unless ($sock)" should be "unless ($main_sock)" {196} last code, lines 8 and 9: ($new_readable) = IO:Select->select($readable_handles, undef, undef, 0); should be: ($new_readable) = IO:Select->select($readable_handles, undef, undef, undef); {196} last code, line 11: "to read from or write to" should be "to read from" (197) First para, first parenthetical stmt: "(or has an error" should be "(or there's been an error" {206} second line of table, 2nd column: "rcv_callback" should be "rcv_cb" to match left hand side {208} list of attributes, description of "sock" should be "The socket object (of the class IO::Socket::INET class)" {208} Last entry in list: "and bytes_to_read contains the bytes still expected" should be "and bytes_to_read contains the number of bytes still expected" {209} Last code block, first large comment chunk: "return only if there's an error" should be "return immediately if there's an error" {212} line 10 of code: $offset = length($msg) - 1; should be $offset = length($msg); {213} first paragraph, first word: "_read" should be "_rcv" [214] in lines 3 and 10: fcntl($_[0], ......) should be replaced with: my $conn = shift; fcntl($conn->{sock}, ......) (214) last paragraph, last line: "run" should be typeset in Courier instead of Italic. {217} Code under comment "Server stuff", and again at bottom of page. RPC->new_rpc_server should be: RPC->new_server (217) last paragraph, last line: "1" should be typeset in Courier {225} para. 2, line 1: "contains the resize handles" should be "is surrounded by the resize handles" (227) last para: "Once Perl/Tk is ported to the Windows and Mac" should be "On Windows and the Mac" [232] Code: The code and the comment says pi radians = 90 degrees, when it should be 180 degrees. (233) lines 2-3: "Guido Von Rossum" should be "Guide van Rossum" {233} Section "Inserting text at absolute positions": "column 5" should be "column 6". [233,234] All code snippets involving insert(): The insert method on the text widget requires the index to be the first parameter and then the text. The code examples illustrating insert show the first and second parameters in the reverse order. So, each of these lines: $t->insert ("Sample", "2.5") $t->insert ("Sample", "end") $t->insert ("Sample", "insert + 5") $t->insert ("Sample", "insert linestart") $t->insert('Sample', '3.5', 'foo'); should read as follows: $t->insert ("2.5", "Sample") $t->insert ("end", "Sample") $t->insert ("insert + 5", "Sample") $t->insert ("insert linestart", "Sample") $t->insert('3.5', 'Sample', 'foo'); {234} Third para from bottom: "and apply a section" should be "and apply formatting" {240} line 4: "[N$scrollbar]" should be "[$scrollbar]" (240) Figure 14-7: "Maserati" spelled wrongly (241) fig 14-8: Caption: change "Celsuis" to "Celsius". {241} line 12 of code: this line should not have a '.' at the end, because the next line has a dot at the beginning. (245) Figure 14-10: The bottom-left annotation should read "...it expands the label to..." (248) Second para: "bind" should be typeset in Courier. {251} 4th line from bottom of code: missing close paren after !!!" {256} First para, second line: "nullifies %block" should be "nullifies @block_cells" (256) first paragraph: "addtag" should be typeset in Courier. {260} code sample 2 (and the example file /examples/GUI/tetris.pl): When I try to run /examples/GUI/tetris.pl I get the following error: Odd number of argsMainWindow->new(Tetris - Perl/Tk) at tetris.pl line 481 The offending line is line 2: $w_top = MainWindow->new('Tetris - Perl/Tk'); From the source for Perl/tk it looks like this should be something like $w_top = MainWindow->new(-screen => $ENV(DISPLAY)) or some kind of a handle to a display. the line should be $w_top = MainWindow->new(-title => 'Tetris - Perl/Tk'); (261) last paragraph: "man perl" should be typeset in Courier. [274] line 9: Employee *Create(); should be: static Employee* Create(); <278> Figure 17-2: "parser()" should be "parse()" (2 instances) (278) Figure 17-2: "add_prop_list" should be "add_prop_list()" (280) first full para, first line: "Ast::visit" should be typeset in Courier {282} Table: Table mentions @IF @ELSE ... but code does not implement it. (284) para. 2: "open_file" should be typeset in Courier instead of Italic (285) last line: "foo" should be typeset in Italic and not in Courier (it's a filename) (289) Resource #1 should read: 1. Berkeley yacc for Perl, available from CPAN under src/misc/perl-byacc.tar.Z (292) First para, next-to-last line, "appropriate function deletes the memory" should be "appropriate function frees the memory" [296] line 4 of the last code example should read: 'LIBS' => ['-L/usr/local/lib -lgd'], # Custom libraries to link with {297} third para under "Fractals Using XS": "OBJECT and LIB" should be "OBJECT and LIBS" <310> Last line under "Using the scripting language's power": last sentence should read: The embedded interpreter approach is taken by the Apache Web server [2]. (Otherwise the previous statements give the wrong impression about Apache.) [311] the code example uses the wrong comment character for C code (# comment should be /* comment */, of course) (311) line 2 of last text para.: "Unix" ought to be "UNIX" (315) paragraph before second code block, last line: "nice_number" should be typeset in Courier. {316} first code line: "main()" should be: int main(int argc, char **argv, char **env) [316] Example 19-3 also has the wrong comment format [316] last statement in code: Change call to perl_close() to: perl_destruct(my_perl); perl_free(my_perl); return 0; (321) Figure 20-1: change "Symbol tabels" to "Symbol tables" {321} First line after the header "Architecture": "shaded rectangles" should be "dark shaded rectangles" (322) Last paragraph: change "there are other stacks to track temporary...and so on" to: there are other stacks to track temporary variables generated during computations, values for local variables, loop iterators, the next opcode to execute on encountering last, redo or return, and so on. The words "last", "redo", and "return" should be in Courier. {324} first para of "Inside Opcodes": "structure called op" should be "structure called OP" (328) Last line before heading "Executor": change "denial of resource" to "denial of service" {330} Table 20-1: SVTYPE should be SvTYPE (330) description for "sv_isa": "sv_isa" should be typeset in Courier. {332} line -5 of code: the call to create_envt_vars() should contain a parameter: create_envt_vars(env); [338] The entry for hv_iterinit is wrong. It says that hv_iterinit returns the number of entries, but it only returns xhv_fill. {339} Figure 20-5: xhv_keys should have "5" next to it, not "6" {343} table 20-5, Description for perl_get_cv: the second sentence should be: You should always set create to FALSE, because a TRUE value automatically creates a blank CV if the subroutine is not present, which is useless to an application writer. {343} table 20-5, Description for perl_call_sv: "(Yes, you'll need to cast the CV to an SV.)" should be: "(Yes, you'll need to cast the CV* to an SV*.)" {347} sub new() near bottom of page: Not really a bug, but a matter of style (Unnecessarily using global variables) Insert my ($rs_increment, $rs_abc); after the line: my $abc = 10; {349} last line: the inner set of parens should be deleted, to make: MAGIC *m = mg_find(sv,'~'); (354) description of XSRETURN_NO: "undef" should be typeset in Courier. {359} First para after code, line 3: "would not be an issue for ANSI C or C++ compilers" should be "would not be an issue for C++ compilers" {359} Last piece of code, plus first piece of code on next page: permute should not call "free(ret)" because ret has been modified. for (; *ret; ret++, i++) { XPUSHs (sv_2mortal(newSVpv(*ret, 0))); } free (ret); should be: char **p = ret; for (; *p; p++, i++) { XPUSHs (sv_2mortal(newSVpv(*p, 0))); } free(p) (366) last line: "SWIG" should NOT be typeset in Courier. {371} #4: Remove "Works only on Unix". {374-375} Button/command, Radiobutton/command, and Checkbutton/command: "is released over the button" should be "is clicked over the button" in all three {379} Entry/sel.first: "Indicates the first and last character of a tag" should be "Indicates the first and last character of the selection range" (383) Table A-11 caption: Remove "(in addition to Table 8-1)" {386} #2, Array References, line 2: "# reference to anon. scalar" should be "# reference to anonymous array" [389] #17, line 3 of code: create(String n, int age): _name(n), _age ...... should be Employee(String n, int age): _name(n), _age ...... [390] #18, line 2 of code: "Employee->new" should be "Employee->create" {391} last line, comment: "if it supports method "foo"" should be "if it supports method "bar"" (index) Additions Brian Kernighan - p. xiv MethodMaker - p. 132 Polymorphism - p. 107 eval function, query processing - p. 182 (index) Changes "malloc command" to "malloc function" "variables/Varable suicide" to "variables/Variable suicide" "stores procedures" to "stored procedures" "nonnblocking" to "nonblocking"