Home / Alt manpages / pl2pm(1)

  • pl2pm(1)
  • User command
  • linux

Convert a Perl 4 Library with pl2pm, Then Review the Module

You will produce a first-pass Perl 5 .pm module from an old Perl 4-style .pl library, check that the generated file compiles, and keep the original available for comparison. Allow 15 to 30 minutes for a small library, plus as much review time as the code needs. The installed command here comes from the Perl package at version 5.38.2-3.2ubuntu0.6, and the local manual describes it as a rough conversion aid rather than a complete translator.

This is an ordinary, unprivileged workflow. Work in a copy or a version-controlled checkout. Do not run the conversion against a system library or a directory where you cannot easily recover the original.

1. Check the command and make a working copy

Confirm which executable will run, then copy the source library into a scratch directory. Replace the example paths with your own. The source filename must end in lowercase .pl; that suffix is how pl2pm decides which input files to translate.

$ command -v pl2pm
/usr/bin/pl2pm
$ mkdir -p ~/pl2pm-work
$ cp --preserve=all /path/to/legacy/widget.pl ~/pl2pm-work/

Checkpoint: the input should still be present and unchanged.

$ ls -l ~/pl2pm-work/widget.pl
$ sha256sum /path/to/legacy/widget.pl ~/pl2pm-work/widget.pl

Do not use sudo for these commands. If the source is readable only by root, fix the working-copy arrangement through your normal access process rather than making the whole conversion run as root.

2. Run pl2pm on the copied library

Pass one or more input filenames. There are no documented options in the local manual, and the command writes the result beside each input rather than to standard output.

$ cd ~/pl2pm-work
$ pl2pm widget.pl
$ ls -l widget.pl Widget.pm

The output name is formed by changing .pl to .pm and capitalising the first word-like part of the basename. For widget.pl, the installed command therefore creates Widget.pm. The generated module starts with a package declaration, a Perl version requirement, Exporter setup and an export list, followed by transformed source.

A successful run normally prints nothing. Verify the result by looking at its beginning:

$ sed -n '1,24p' Widget.pm
package Widget;
use 5.006;
require Exporter;

@ISA = qw(Exporter);
@EXPORT = qw(...);

The exact export list and body depend on the input. Treat the displayed structure as a shape to check, not as a promise that every legacy construct will be handled correctly.

3. Understand what the first pass changes

The installed script makes mechanical substitutions intended for Perl 4 libraries. It can translate old package-qualified variable and subroutine references, remove some old $[ idioms, change simple open NAME calls to open(NAME), and turn die into croak while adding use Carp;. It also recognises a matching require 'widget.pl'; line and changes it to a module-style use Widget reference.

That list is deliberately limited. It does not prove that the code now follows modern Perl module conventions, handles warnings correctly, or preserves the intended behaviour. The manual calls the utility a first step. In particular, inspect regular expressions, indirect filehandles, global variables, package boundaries, export choices and code that depends on Perl 4 semantics.

Checkpoint: compare the generated file with the original instead of replacing the original.

$ diff -u widget.pl Widget.pm
$ git diff --no-index -- widget.pl Widget.pm

The second command returns a non-zero status when differences exist, which is normal here. Do not interpret that status as a failed conversion.

4. Compile the generated module

Use Perl's syntax-only check before trying to load the module into an application:

$ perl -c Widget.pm
Widget.pm syntax OK

This checks syntax and compile-time activity. It does not test exported functions, file handling, runtime data, or compatibility with the program that used the old library. If it reports an error, edit a separate review copy or return to the source, correct the problem deliberately, and rerun the check.

For a module that is safe to load in your test environment, add its directory to Perl's library path and ask Perl to load it:

$ perl -I. -MWidget -e 'print "loaded\\n"'
loaded

Loading a module can execute compile-time code, so use a disposable test environment when the legacy library has side effects or reads configuration. Do not use this command as a substitute for the module's test suite.

5. Avoid accidental overwrites and misleading inputs

pl2pm will not overwrite an existing output file. If Widget.pm already exists, it warns and skips that input:

$ pl2pm widget.pl
Won't overwrite existing Widget.pm

That protection is useful, but it does not create a backup or merge changes. Decide whether the existing module is the one you meant to keep before moving it aside. If you intentionally want a fresh result, rename the old output in your version-controlled working copy, run the command, and retain the old file until review is complete.

Do not pass --help or --version expecting normal option handling. The installed program has no such documented interface and treats command-line arguments as input filenames; a missing file produces a Perl file-open error. A file whose name does not end in .pl is skipped rather than converted, so check the spelling of every input name.

6. Finish the migration manually

Keep the original .pl file until tests show that the module behaves correctly. Update callers to load the module using the package name, review @EXPORT and prefer explicit imports where appropriate, then run the application's tests. Add module documentation and a deliberate interface rather than treating the generated export list as an API design.

If the migration is abandoned, recovery is simple: discard only the generated .pm from the scratch copy. If it has already been committed, restore it through version control after checking the path and commit. Never delete the only copy of the original library as part of this conversion.

Done means

  • The original .pl file remains available and unchanged.
  • pl2pm created a new, correctly named .pm file beside the copy.
  • The generated module passed perl -c.
  • You reviewed the diff and the generated exports instead of trusting the mechanical translation.
  • Application tests cover the behaviour that the old library provided.