Using

Scripting

Debugging XChat Perl Scripts

So you have written a Perl script and loaded it, just to have XChat spit out a bunch of lines and say the script didn't load. What happened? Each of the lines means something, and lucky for you, the messages normally include the line (or a line close to) where the problem occurred. But even after you get XChat to load the script without complaint, this doesn't mean the script will work as intended.

First thing is first: the syntax of the script needs to be correct. There are two ways of doing this:

  1. Loading the script into XChat and looking for the errors
  2. Using Perl's syntax checker outside of XChat

Using XChat to verify syntax

The simplest way to test your script for syntax errors is to load the script directly into XChat. There are multiple ways of doing this:

  • XChatLoad Plugin or Script, browse for the file and hit OK
  • WindowPlugins and ScriptsLoad, browse for the file and hit OK
  • /load /path/to/file.pl
  • /pl_reload /path/to/file.pl

It will many times be easier to use one of the last two options while developing scripts, as loading the file once again is as simply a few up arrow keys presses and enter. /pl_reload has the advantage over /load in that /pl_reload acts like /load when the script isn't loaded, but will reload the script if it is loaded. This way you only need one command regardless of if the script wasn't loaded before, failed to load the previous time, or was already loaded. /pl_reload is named for Perl reload and therefor doesn't call the routines of other language interpretors, such as TCL.

Consider the following code:

  1. Xchat::hook_command('hi', sub {
  2.         my $string = 'hi'
  3.         $strig = $string . ' ', $_[1][1];
  4.         Xchat::command("say $string");
  5.         return Xchat::EAT_ALL;
  6. });

When loaded into XChat, XChat returns the following message:

 Error loading '/home/user/.xchat2/bad_script.pl':
 syntax error at /home/user/.xchat2/bad_script.pl line 3, near "'hi'
 $strig "

Note that the $strig is on line 3, but the error is actually that there should be a semicolon at the end of line 2. This is quite common when loading Perl scripts into XChat, as the scripts get evaluated rather than compiled (which is what happens when run from the command line). Later on, we will see what the error would be if testing from the command line, but for now, it is good enough to know the general area of the error.

Even though $strig was mentioned, XChat and Perl didn't catch this typo, it just happened to be the next word. When Perl is feeling forgiving, it allows variables to be initiated without being declared with a my. The load also did not catch the fact that the comma was used after the ' ' instead of a period. For these reasons, it is important to start out each of your scripts with the following two lines:

use strict;
use warnings;

With these two lines added (leaving the semicolon out for example purposes), we have the following code with associated error message on load:

  1. use strict;
  2. use warnings;
  3. Xchat::hook_command('hi', sub {
  4.         my $string = 'hi'
  5.         $strig = $string . ' ', $_[1][1];
  6.         Xchat::command("say $string");
  7.         return Xchat::EAT_ALL;
  8. });
 Scalar found where operator expected at (eval 21) line 5, near "'hi'
 $strig"
 (Missing operator before 
 $strig?)
 Error loading '/home/user/.xchat2/bad_script.pl':
 syntax error at /home/user/.xchat2/bad_script.pl line 5, near "'hi'
 $strig "
 Global symbol "$strig" requires explicit package name at /home/user/.xchat2/bad_script.pl line 5.
 Global symbol "$string" requires explicit package name at /home/user/.xchat2/bad_script.pl line 5.

Note how now, XChat actually states that there may be a missing operator (the semicolon) before $strig. There are extra line breaks displayed in the channel due to the syntax error happening at the end of the line and XChat printing the context around the code. With use strict; use warnings; specified, Perl will report the generic error followed by a more detailed description.

The error message then goes on to state that Global symbol "$strig" requires explicit package name. This occurs because $string was declared with a my, but not $strig, this is an effective means of finding typos in variable names.

The last error that is reported turns out not to be an additional error, but a side effect of the missing semicolon. Still, $string is used in the 5th line without it having been declared earlier. Many times when earlier errors are fixed, later ones will be fixed at the same time.

After fixing these errors, we have the following code and associated load message:

  1. use strict;
  2. use warnings;
  3. Xchat::hook_command('hi', sub {
  4.         my $string = 'hi';
  5.         $string = $string . ' ', $_[1][1];
  6.         Xchat::command("say $string");
  7.         return Xchat::EAT_ALL;
  8. });
 Useless use of array element in void context at /home/user/.xchat2/bad_script.pl line 5.

The message warns about the array, which is formed when the comma is used, but technically speaking, the script "works" but will only say "hi " to the channel, and nothing else. This problem was caught by the use warnings; after the major syntax problems were fixed. Even though the warnings may not make any sense, look over the line a few times, because there is most likely something wrong with the line. The script will have loaded into XChat this time, but it won't work as intended until the script loads without warning.

After figuring out the comma should be a period, the script will load without problems or warnings, and so by default, no status message will be given.

Using Perl's syntax checker from the command line

XChat does a fairly thorough job of reporting errors when it loads Perl scripts, but the XChat interface isn't necessarily ideal for reading through these messages. If there are a lot of reported errors, this can be quite distracting if you load the file in a channel you are paying attention to. Additionally, anything that is displayed in the chat window gets logged if logging is enabled, and this isn't normally desired.

Perl includes a syntax checker that can be run from the command line. This is done using perl -c filename.pl from the directory where the perl script resides.

As XChat uses functions and variables not present in standard Perl (such as Xchat::EAT_ALL), we need a file to tell Perl how to handle these differences. Copy the plugins/perl/Xchat.pm file from the source into the same directory as where you are running the perl -c from. If you would rather download only this file, you can use the development version of Xchat.pm.

Along with the notes above dealing with the importance of use strict; and use warnings;, XChat Perl scripts should also contain one of the following lines if syntax checked from the command line:

use Xchat;
use Xchat qw(:all);

When the Perl script is loaded into XChat, the Xchat.pm module is already loaded, and so Perl is able to reference it. However when evaluated from the command line, Perl doesn't know what is included in the module without explicitly using the module, so use Xchat; is required. Once the module has been loaded, any additional calls to use Xchat; do not reload the module. Without this though, the Perl command line interpretor doesn't know you are intending to use this script with XChat, or what to do if it did. Without this line, you will get errors such as:

Bareword "Xchat::EAT_ALL" not allowed while "strict subs" in use at valid_script.pl line 12.

By using the second line, you don't need to use all of the instances of Xchat:: everywhere else in the script (as explained on the Basic Perl Script page).

Using the original code in the "Using XChat to verify" section, but adding use strict; use warnings; use Xchat;, note how the errors are different:

  1. use strict;
  2. use warnings;
  3. use Xchat;
  4. Xchat::hook_command('hi', sub {
  5.         my $string = 'hi'
  6.         $strig = $string . ' ', $_[1][1];
  7.         Xchat::command("say $string");
  8.         return Xchat::EAT_ALL;
  9. });

Running the command perl -c bad_script.pl results in the following output:

Scalar found where operator expected at bad_script.pl line 6, near "$strig"
	(Missing semicolon on previous line?)
syntax error at bad_script.pl line 6, near "$strig "
Global symbol "$strig" requires explicit package name at bad_script.pl line 6.
Global symbol "$string" requires explicit package name at bad_script.pl line 6.
bad_script.pl had compilation errors.

Note how the error is more specific about the need for a semicolon the previous line rather than just a missing operator. Otherwise though, the errors are pretty much the same, although shorter as the entire path isn't used. As before, fix the errors in question to obtain the following code and message:

use warnings;
use strict;
use Xchat;
Xchat::hook_command('hi', sub {
        my $string = 'hi';
        $strig = $string . ' ', $_[1][1];
        Xchat::command("say $string");
        return Xchat::EAT_ALL;
});
Useless use of array element in void context at bad_script.pl line 6.
bad_script.pl syntax OK

Unlike loading the script in XChat, using the command line syntax checker will report that the syntax was OK. Just as before there was a problem with the comma, it still exists, but since the script technically works, the syntax is declared OK.

After fixing the comma to period issue, running perl -c will simply report that the syntax is OK.



Print - Recent Changes - Search
Page last modified on June 30, 2010, at 02:28 PM