Revision history for Perl extension NetAddr::IP

4.080_04  2026-10-09 19:50:39+11:00 Australia/Sydney (TRIAL RELEASE)

    Fix GH#109: The wrap check in the Util EXAMPLES compared addresses as
    strings, so text order stood in for address order. Two snippets stepped an
    address with the overloaded ++ and decided whether the host part had wrapped
    by comparing the string forms before and after. As text 192.0.2.10 sorts
    before 192.0.2.9, so the step from .9 to .10 read as a wrap, and the real
    wrap from .11 back to .8 sorted after, so it read as no wrap. Both snippets
    happened to print what the page said: the first never wrapped, so its
    addconst branch never ran, and every address in the loop had three digits in
    the last octet, where text order and address order agree.

    Stepping every aligned subnet of 192.0.2.0/24 from /24 to /31, 255 nets and
    2048 steps, each net wrapping once, the string test reported 13 false
    wraps and missed 6 of the 255 real ones, in 192.0.2.64/26, 192.0.2.96/27,
    192.0.2.96/28, 192.0.2.8/29, 192.0.2.96/29 and 192.0.2.8/30. Six IPv6 nets
    in 2001:db8::/32 gave 3 false wraps and no missed ones. Comparing the
    objects got all 2048 IPv4 steps and all 4648 IPv6 steps right on both
    builds.

    Both snippets now take $before = $ip->copy and test $ip < $before, the
    overloaded comparison, which subtracts the two 128 bit addresses and is
    address order for either family. A step inside the net raises the address
    and a wrap drops it to the network address, so the new address is the lower
    one only at a wrap. The first snippet starts at 192.0.2.127/26 and steps by
    64, so it takes the wrap branch and shows the addconst list assignment the
    paragraph above it is about; it prints 192.0.2.128/26, where the string
    test prints 192.0.2.64/26. The loop starts at 192.0.2.8/30, which passes
    both failure points, and its output follows as result comments. The
    paragraph between them had called the overloaded < the wrong test, when it
    is the right one, and had said comparing string forms is what detects the
    wrap; the only fault in the original test was $ip-copy(), which is not
    Perl. No code outside the examples changes.

Fix GH#111: Build XS by default where a compiler works, and delete the
    checkout Makefile.PL. Three edits in 4f61b57 combined
    to disable the compiler test: $useXS was initialised to 0 rather than left
    undefined, which also made the new "!defined $useXS" test in the Windows
    rule permanently false; the probe condition became "if ($useXS)" rather
    than "unless (defined $useXS)", so it ran only when --xs was given; and a
    successful probe no longer set $useXS = 1. So a plain "perl Makefile.PL"
    wrote the pure Perl Makefile everywhere. That is the command cpan and
    cpanm run, so an install from the next release would have built pure Perl
    even where a compiler works, and the Linux CI job meant to test the XS
    has been testing pure Perl while staying green. The same commit also
    dropped the closing brace of an "if ($useXS)" block, so the checked-out
    Makefile.PL no longer compiled at all.

    header.pl leaves $useXS undefined until an option or the platform rule
    sets it, runs the probe when neither --xs nor -noxs was given, and sets
    $useXS = 1 when a compiler works. That restores the 4.079 default while
    keeping the 4f61b57 change that lets --xs override the Windows rule. With
    --xs the probe is skipped and the build is XS, as in 4.079; a broken
    compiler now fails at make instead of falling back to pure Perl, which is
    what asking for the XS explicitly should mean.

    Each of the four build jobs now checks the mode it got rather than
    passing as whichever build it happened to produce. t/033-util-mode.t
    cannot do this: it derives its expectation from Util_IS->not_pure, so it
    agrees with the build either way. The macOS job asserts Pure Perl, which
    is the point of pinning it down, since it gets there by the accident that
    "darwin" contains "win" and so matches the /win/i platform rule.

    The checked-out Makefile.PL is deleted rather than repaired. It is
    excluded from the distribution, nothing regenerates it, and it had
    drifted from inc/MakeMaker: it still used the older %makeparms spelling
    instead of @mm_args, and carried a realclean naming xs/config.h,
    xs/config.log and xs/config.status, which GH#101 stopped generating, plus
    a clean override protecting lib/NetAddr/IP/Util.c, which GH#96 established
    is not tracked in git. README.md now says so and gives the dzil build
    path.

    Restoring the XS build exposed a fault in the clean list that the pure
    Perl default had been hiding. make clean did not remove
    lib/NetAddr/IP/Util.o, because ExtUtils::MakeMaker only knows about
    C_FILES and OBJECT when the XS branch fills them in, so the file survived
    a clean, then a later perl Makefile.PL -noxs in the same tree copied it
    into blib as though it were a module, which dragged the postamble's xsubpp
    rule into a pure Perl build where $(XSUBPP) is unset. That failed on
    "-ypemap". The clean list now names Util.c, Util.o and Util.c.xsc as well.
    All three are generated, and in a pure Perl tree naming absent files costs
    nothing.

    Fix GH#114: The XS build had not compiled since GH#106, so CI never
    noticed: its Linux XS job builds pure Perl, see GH#111. The file carried
    two definitions of _num_arg and two of have128 with no body. It was
    missing _128x10plusbcd, which _bcdn2bin still called, and the unused
    _isipv4. It used k and nv in comp128 and bcd2bin without declaring them,
    and read the packed argument with SvPV rather than SvPVbyte in seven
    functions. Restored GH#106 as filed, tests included: the duplicate is
    gone, have128 keeps its GH#102 unaligned access fix, the missing helpers
    are back, the packed argument is read with SvPVbyte while the digit text
    in bcd2bin and simple_pack stays SvPV, and a count or constant is read
    before a pointer into the address is taken. A fifth defect in the same
    area: a packed address reached through get magic looked undefined.
    _packed_ok runs the magic once and reports whether the value is then
    defined, _packed_bytes reads the bytes without running the magic again
    and through a downgraded copy when the argument is upgraded.
    SvPVbyte_nomg would do this in one call but needs perl 5.31.4, so this
    uses only calls available from 5.9.2.

    Fix GH#101: Remove the autoconf/configure step. The XS build ran one of
    two autoconf scripts to write xs/config.h, and the C code takes exactly
    two facts from that file: the host byte order and a pair of 32-bit integer
    types. Both have been in perl.h since at least 5.005_03. The configure step
    can go: four files, 31 percent of the compressed tarball, about 60 lines of
    the Makefile.PL header, and the reason the module has historically given
    for building pure Perl on Windows.

    Fix GH#102: Four helpers in xs/Util.xs read the caller's packed address as
    32-bit words through a cast of the Perl string buffer. That is undefined
    behaviour in C whenever the buffer is not 4-byte aligned, and Perl hands
    the XSUBs unaligned buffers in ordinary use. A string whose leading bytes
    were removed in place keeps its allocation and moves its start. On x86 and
    arm64 the loads still give the right answer, which is why nothing has
    failed; on hardware that traps misaligned loads, SPARC above all, the
    process dies with SIGBUS. The fix copies the bytes into local words with
memcpy, which compiles to the same instructions where unaligned loads are
    cheap.

    Fix GH#7: Document that uppercase is the effective default, not lowercase.
    InetBase said "This module defaults to lowercase", which holds only when
    it is loaded on its own. NetAddr::IP::Util loads it with :upper, so every
    program that uses NetAddr::IP prints uppercase. The case setting is
    process wide and the last import or call wins, so a lower() anywhere
    changes what every object prints. InetBase, IP.pm and Lite.pm now say so.

    Fix GH#12: The :aton packed input is corrupted by lc for bytes 0x41 to
    0x5A. The _xnew() function in Lite.pm ran $ip = lc $ip; before checking
    whether the input was a packed binary address, so bytes 0x41-0x5A (A-Z)
    became 0x61-0x7a (a-z). Fixed by preserving the original input in $raw
    before lowercasing, and using it for the binary IP detection path.

    Fix GH#21: ipv6_aton accepts a single leading or trailing colon, which
    RFC 4291 section 2.2 does not allow. The pure-Perl build shares this code
    and behaves the same way. Fixed by adding explicit checks for a single
    leading or trailing colon before processing.

    Final polish: constructor entry cleanup and import tag refinement.

    Unify the argument names and finish the import tag tables (GH#100, C5
    and C7), the last two items from the structure list.

    C5 named one concept six ways across the three function pages. For a
    16 byte string there were $ipv6naddr, $ipv6addr, $pv6naddr, $bits128
    and $netaddr. Now $bits128 is the 16 byte string, $ipv6naddr an
    address being converted, and $netaddr a 4 byte one:

      $bits128     52 -> 60 uses, after the sweep
      $ipv6naddr   48 -> 50
      $netaddr     29
      $ipv6addr     8 -> 0
      $pv6naddr     2 -> 0

    $pv6naddr was a typo for $ipv6naddr, in two places. Checked first that
    every occurrence of both names was POD or POD inside a comment, so no
    code was renamed:

      $ipv6addr in non-POD code   0 lines in each of the three files

    C7, three pages carried an import tag section and Lite.pm carried none,
    and none of them said what happens when :lower and :upper are both
    given. Verified rather than assumed, in both classes:

      NetAddr::IP          :lower          2001:db8:0:0:0:0:0:1
      NetAddr::IP          :upper          2001:DB8:0:0:0:0:0:1
      NetAddr::IP          :lower :upper   2001:DB8:0:0:0:0:0:1
      NetAddr::IP          :upper :lower   2001:DB8:0:0:0:0:0:1

    :upper wins either way, because :lower is handled first in import.
    Lite.pm now has an IMPORT TAGS section covering the five tags it
    accepts, each marked process-wide, and the precedence stated. Which is
    the five was measured, since :old_storable and :rfc3021 belong to
    NetAddr::IP alone:

      :old_storable   rejected by Lite
      :rfc3021        rejected by Lite
      :aton           accepted
      :old_nth        accepted
      :nofqdn         accepted

    Documentation only, no code change.

    Group the remaining method and function entries (GH#100, C2 and the
    grouped layout). IP.pm was grouped in the previous commit; this does
    the other four.

      Util.pm      34 entries into Text to binary, Binary to text, Case,
                   Family tests, Widening and narrowing, Arithmetic,
                   Decimal strings, Resolver, Build mode
      InetBase.pm  21 entries into Text to binary, Binary to text,
                   Family tests, Address family, Short IPv4 text, Case
      UtilPP.pm    13 entries into Family test and shift, Arithmetic,
                   Widening and narrowing, Decimal strings
      Lite.pm      27 entries into the six groups it has, the same names
                   IP.pm uses where they overlap

    Each entry block was moved whole and checked to have survived
    verbatim, and both the definition count and the POD item count are
    unchanged in all six modules:

      IP.pm       31 subs, 67 items
      Lite.pm     50 subs, 39 items
      Util.pm      7 subs, 41 items
      InetBase.pm 29 subs, 25 items
      UtilPP.pm   28 subs, 13 items
      Constants.pm 0 subs, 14 items

    Two things worth recording about how this went.

    podchecker needs =head2 outside an =over, so each group is its own
    list rather than headings inside one list. It also needs a blank line
    before =back, or the =back is swallowed as ordinary text and the list
    reads as unclosed. That only bit one group, because the group whose
    entries happened to be last in the old order had no trailing blank
    line to inherit. The error pointed at the next =head2, which sent the
    first two attempts looking for an imbalance that was not there; the
    cause only showed up when the block was reproduced in three lines.

    UtilPP.pm had two =head1 DESCRIPTION sections, one of them a single
    line left over from the step 2 rewrite, and no FUNCTIONS heading at
    all. Both fixed here.

    C3 finished at the same time: INSTALLATION is now gone from every
    module. It was already gone from Util.pm, InetBase.pm, UtilPP.pm and
    Constants.pm; IP.pm and Lite.pm still had it, so the build steps live
    in README.md alone, and the two pages point at it from DESCRIPTION.
    Nothing linked to the removed sections.

    Documentation only, no code change.

    Fix README.md (GH#100, step 4, the last one). It had errors of its own,
    and three of them meant a reader's first attempt at the advanced
    methods died.

    The four calling conventions in the advanced section were all wrong.
    They were written as functions called on the class name, where the
    arguments land in $_[0] where an object is expected:

      NetAddr::IP->split($base,$bits)
        dies: Can't use string ("NetAddr::IP") as a HASH ref
      NetAddr::IP->rsplit($base,$target)
        dies: Can't use string ("NetAddr::IP") as a HASH ref
      NetAddr::IP->hostenum($ips)
        dies: Can't use string ("NetAddr::IP") as a HASH ref
      NetAddr::IP->compact(@ips)
        dies: Can't use string ("NetAddr::IP") as a HASH ref
      NetAddr::IP->coalesce(@ips)
        returns one value, silently

    Every one of them is a method on an object:

      $ip->split(26)                     $ip->rsplit(28,29,28,29,26)
      $ip->splitref(26)                  $ip->rsplitref(28,29,28,29,26)
      $ip->hostenum                      $ip->hostenumref
      $ip->compact(@other)               $ip->compactref(\@other)
      $ip->coalesce($masklen,$number,@other)

    The coalesce case is the nastiest, because it returns rather than
    dying, which is the same silent-wrong-answer shape as GH#39.

    The examples used 192.168.1.123 and fe80::1. Replaced with the RFC
    5737 and RFC 3849 documentation addresses, so nothing in the README
    points at a range someone might own, and the IPv6 outputs are the real
    ones, which are not what a reader would guess:

      new('2001:db8::1/64')->network    2001:DB8:0:0:0:0:0:0/64
      new('2001:db8::1/64')->broadcast  2001:DB8:0:0:0:FFFF:FFFF:FFFF:FFFF/64

    InetBase was described as "low-level inet address conversion (mostly
    XS)". It is pure Perl on every host; UtilPP is the pure Perl half and
    Util is the XS one. The module list also said four modules and gave
    no mention of UtilPP or Constants, so all six are now listed, with
    NetAddr::IP::Util_IS noted as generated.

    is_local was described as "true for 127.x.x.x or ::1", which misses
    the two IPv6 forms the code accepts:

      127.0.0.1=1  ::1=1  ::127.0.0.1=1  ::ffff:127.0.0.1=1

    The export tag table omitted :old_storable, :aton and :rfc3021. All
    three are added and marked deprecated, and the entry for :rfc3021
    says why it is no longer needed.

    Added what was missing rather than only fixing: the mask-argument
    trap, the array deref overload and the two croaking operators, the
    comparison order, the /31 and /127 host count, the split croak, a
    worked example showing split and rsplitref actually differing on the
    same plan, and a Functions section for Compact, Coalesce and
    netlimit, which had no home at all.

    The Authors section listed two of the three, and gave an address for
    Michael Robinton that is not the one in dist.ini. It now matches
    META.json.

    Documentation only. No module was touched, checked by counting
    definitions before and after: IP.pm 31/31, Lite.pm 50/50, Util.pm
    7/7, InetBase.pm 29/29, UtilPP.pm 28/28, Constants.pm 0/0.

    Group the IP.pm methods, rewrite its SYNOPSIS, and document netlimit
    (GH#100, step 3 continued). The Methods section was one flat =over of
    forty-eight entries, so a reader looking for how to enumerate hosts
    scanned forty-eight headings. It is now ten =head2 groups, each its
    own =over:

      Constructors           new new6 new_no new_from_aton
                             new_cis new_cis6
      Address and mask       addr mask masklen bits version cidr aton
      Boundaries             network broadcast first last range
      Numeric forms          numeric bigint
      Text forms             short canon full full6 full6m prefix
                             nprefix wildcard
      Containment            contains within is_rfc1918 is_local
      Splitting              split splitref rsplit rsplitref
      Set operations         compact compactref coalesce
      Hosts                  num nth hostenum hostenumref
      Regular expressions    re re6

    That reorders entries, so each block was moved whole and checked to
    have survived verbatim; 48 of 48 did, and the POD item count is
    unchanged at 63. podchecker needs =head2 outside an =over, so each
    group is its own list rather than one list with headings inside it.

    The SYNOPSIS was 113 lines: an import list, every signature, the
    case policy, the FQDN note, Storable, Compact, Coalesce and
    netlimit, all of it mixed together. It is now fifteen pasteable lines
    with results in comments, and the material that was not a synopsis
    moved to its own IMPORT TAGS section:

      print $ip->addr, "\n";         # 192.0.2.1
      print $ip->mask, "\n";         # 255.255.255.0
      print $ip->network, "\n";      # 192.0.2.0/24
      print $ip->broadcast, "\n";    # 192.0.2.255/24
      print "$ip\n";                 # 192.0.2.1/24
      my $next = $ip + 5;            # 192.0.2.6/24
      my @halves = $ip->split(25);   # 192.0.2.0/25, 192.0.2.128/25

    B11, netlimit was documented only inside the SYNOPSIS, which is where
    the code lived too, and it returns the new limit rather than "true on
    success". It has a FUNCTIONS section now, and the values are the
    measured ones:

      netlimit(20)   1048576
      netlimit(16)   65536
      netlimit(24)   16777216
      netlimit(10)   undef, below the default
      netlimit(25)   undef, above the maximum

    B4 through B7 are documented under the constructor, where the
    abbreviated accepted-forms list is, with the mask-argument trap
    spelled out since it is the one that surprises:

      new('10.1')        10.0.0.1/32
      new('10.1', 8)     10.1.0.0/8
      new('10.1.2')      10.1.0.2/32
      new('10.1.2', 24)  10.1.2.0/24

      new('192.0.2.4-7')         192.0.2.4/30
      new('192.0-3.')            192.0.0.0/14
      new('[2001:db8::1]/64')    2001:DB8:0:0:0:0:0:1/64
      new('[192.0.2.1]/24')      undef

      new('broadcast')       255.255.255.255/32
      new6('broadcast')      undef, IPv4 keywords only
      new('loopback')        127.0.0.1/8, not /32

    And one correction to what I wrote in the previous commit for this
    step: moving the SYNOPSIS deleted the netlimit sub and its $_netlimit
    default, because the code sat between that heading and INSTALLATION
    and the replacement spanned both. perl -c did not catch it and the
    suite still passed 2535 tests, since nothing calls netlimit. What
    caught it was documenting the function and finding
    NetAddr::IP->can("netlimit") was undef. Restored, in the FUNCTIONS
    section this time. Every edited file was then checked for lost
    definitions:

      IP.pm 31 subs before, 31 after, identical set
      Lite.pm 50/50, Util.pm 7/7, InetBase.pm 29/29,
      UtilPP.pm 28/28, Constants.pm 0/0

    plus the glob aliases, which also match.

    Fix NetAddr::IP and NetAddr::IP::Lite (GH#100, step 3). The two pages
    carry the same object API and have drifted, so they go in one commit
    and the merged text is written once.

    A4, both said splitref "returns undef when bits ... will not fit". It
    croaks:

      NetAddr::IP->new('192.0.2.0/24')->splitref(16);
      # netmask error: overrange or spurious bits

    A6, the IP.pm SYNOPSIS listed inet_any2d and inetanyto6. Neither
    exists; they are inet_any2n and ipanyto6, both of which Util has.

    A11, both new() entries said 'See "STRINGIFICATION" below.' There is
    no such section on either page.

    A12, "The first two methods create..." followed by "The third method
    new_no", after six constructors had been listed. new6FFFF was absent
    from IP.pm's list altogether and works through inheritance, so the
    entry now names it and shows the object it makes:

      NetAddr::IP->new6FFFF('192.0.2.1');
      # 0:0:0:0:0:FFFF:C000:201/128

    A13 is Util.pm, A17 is below. A19, IP.pm's DESCRIPTION promised
    NetAddr::IP "will work with older versions of Perl". META.json says
    5.014, so that is now stated.

    A20 and A22 are the drift between the two pages. IP.pm listed two
    is_local forms where Lite.pm listed four, and Lite.pm's within()
    carried a sentence about comparing addr() that IP.pm lacked. Both are
    merged, verified against the code:

      127.0.0.1        is_local=1
      ::1              is_local=1
      ::127.0.0.1      is_local=1
      ::ffff:127.0.0.1 is_local=1
      ::ffff:10.0.0.1  is_local=0
      128.0.0.1        is_local=0

    The entries are now byte-identical between the two files, which is
    checkable:

      is_local()  identical    mask()  identical     first()  identical
      within()    identical    bits()  identical     last()   identical

    A21, Lite.pm carried the numeric() float-comparison warning and IP.pm
    did not. It is on both now, with the hazard shown rather than
    described, because it is silent:

      $x->numeric == $y->numeric   same    for 2001:db8::1 and ::2
      $x == $y                     different
      $x->bigint == $y->bigint     different

    A23, both new_cis item headings had an unbalanced quote.

    A25, prefix() was documented as including the broadcast address. The
    range starts at first(), not network():

      192.0.2.4/30  ->  192.0.2.5-7
      192.0.2.0/24  ->  192.0.2.
      192.0.2.0/20  ->  192.0.0-15.
      192.0.2.9/32  ->  192.0.2.9

    A27, both pages warned that comparing objects of differing CIDR "may
    produce indeterminate - unexpected results". It is deterministic:
    address first, then the mask as a number. The warning was wrong, and
    the real caveat is that the order is not the one most people mean by
    "bigger", so it says that instead and shows the sort order.

    A28, both listed "a netaddr as returned by 'inet_aton'" among the
    accepted forms without saying it needs the deprecated :aton tag.
    Without it a packed string returns undef, which is now stated. The
    RFC 1884 citations became RFC 4291 s2.2 on both pages.

    A17, the IP.pm NOTES / BUGS section said in the first person that the
    author lacked the resources to get the configure step working on
    Windows and asked for volunteers. It now states the fact and where it
    comes from, which is that header.pl selects pure Perl when $^O
    matches /win/i, and points at README.md for the build steps.

    B1 and B2, the @{} overload and the croaking neg and abs, were
    undocumented on both pages:

      scalar @{$ip}   14 for a /28
      -$ip            cannot negate a NetAddr::IP object
      abs $ip         cannot take the absolute value of a NetAddr::IP object

    B3, the sort order is now given as part of the comparison entry.

    C4, version history inside method text is gone from nth() and num() on
    both pages. Both entries carry measured output instead:

      /32 nth(0) is the address itself, num 1
      /31 nth(0) is the network address, num 2
      /30 nth(0) is the first host, num 2
      /28 num 14

    and the C<:old_nth> tag still restores the old behaviour, verified:

      old_nth 192.0.2.0/30  nth 0 undef, 1..3 the hosts, num 3

    C9, IP.pm's HISTORY section, which said only "See the Changes file",
    is removed and the internal link now points at DEPRECATED.

    Also fixed in passing: "array contest" for "array context" in IP.pm
    and Lite.pm numeric(), a doubled space in Lite.pm bigint(), and the
    C3.02 version note in compact().

    POD only, no code change. Still outstanding from this step: the
    =head2 method groups, the SYNOPSIS rewrite, and B4 through B12 for the
    constructor entry, which is where the accepted-forms list lives and is
    long enough to need more than a correction.

    Fix NetAddr::IP::InetBase and NetAddr::IP::UtilPP (GH#100, step 2,
    continued). The two carry copies of the entries fixed in Util.pm, so
    they go in the same step.

    A7, the InetBase SYNOPSIS said "use NetAddr::IP::Base qw(...)", and
    the module is NetAddr::IP::InetBase, so the line as printed could not
    run. It was also followed by a NetAddr::IP::Util line pasted from
    Util.pm showing Util's tags, which InetBase does not have. Both are
    gone; the SYNOPSIS is now InetBase's own nineteen names with measured
    output, and its four tags are listed with their real contents,
    recovered by importing each into a scratch package:

      :ipv4   fillIPv4 inet_aton inet_ntoa, three names
      :ipv6   eleven names

    The old list for :ipv6 was missing four of those.

    A8, InetBase documented ipv4to6. It is neither defined nor exported
    there; the function belongs to NetAddr::IP::Util, and
    InetBase->can("ipv4to6") is undef. The entry is removed.

    A9, InetBase said lower() "is the default" and Util.pm said upper()
    "is the default", and both were right about themselves and wrong
    about the reader's program. Measured:

      InetBase alone:          ipv6_n2x = 2001:db8:0:0:0:0:0:1
      after InetBase::upper() ipv6_n2x = 2001:DB8:0:0:0:0:0:1
      Util loaded:             ipv6_n2x = 2001:DB8:0:0:0:0:0:1

    InetBase defaults to lowercase, and loading Util, Lite or NetAddr::IP
    imports :upper for you, so in practice uppercase is the default for
    nearly every program. There is now one section, THE CASE POLICY, that
    says so once, shows the process-wide behaviour where an unrelated
    package importing :lower changes the output for everyone else, and
    points at GH#7 for the open question of what the policy should be.
    ipv6_ntoa and inet_ntop are called out as always lowercase.

    Worth recording, since the old entries implied otherwise: neither
    lower nor upper is importable from either module.

      NetAddr::IP::InetBase->can("lower")   undef
      NetAddr::IP::Util->can("lower")       undef

    They must be called fully qualified, NetAddr::IP::InetBase::upper(),
    and the entries now say so.

    fillIPv4 was documented as converting "127.1 to the long form
    127.0.0.1", which is right, but nothing said what it does with
    anything else, and it is not what a reader would guess. Measured:

      fillIPv4('192.0.2.1')      192.0.2.1
      fillIPv4('192.0.2')        192.0.0.2
      fillIPv4('192.0')          192.0.0.0
      fillIPv4('10')             0.0.0.10
      fillIPv4('example.com')    example.com, unchanged
      fillIPv4('256.1.1.1')      undef

    The argument is text, not a packed address, which is the trap: a
    packed string does not match, so it comes back unchanged. It is also
    the BSD inet_aton convention and not RFC 791, which is the note
    table D asks for, and which belongs here rather than on inet_aton.

    A14, the missing paren in the hasbits example was in this file too,
    at UtilPP.pm:111, so it is fixed in both.

    A15, the UtilPP EXPORT_OK list ended with "threads", which is not a
    function of that module nor of NetAddr::IP::Util; it never existed.
    Removed, and the list now cross references NetAddr::IP::Util instead
    of being a bare list of eighteen names.

    A18's rfc1844 typo was here as well as in Util.pm, and the two rfc1884
    citations became RFC 4291 s2.2.

    UtilPP gets a DESCRIPTION, which it did not have beyond one sentence.
    It explains when the module is selected, that the two implementations
    are meant to be interchangeable and agree down to the error message
    wording, and that README.md carries the build steps, so no page
    discusses building.

    INSTALLATION is removed from InetBase too, per C3.

    A new section on InetBase, SOCKET6 SUBSTITUTION, names the three
    symbols that come from Socket6 when it is installed, says the choice
    is made at load time, and points at GH#99 and GH#21 for where the two
    paths disagree.

    POD only, no code change. The grouped =head2 sections the issue asks
    for across all three function pages, and the table D note about
    inet_aton short forms, are still outstanding.

    Fix NetAddr::IP::Util (GH#100, step 2 of the POD overhaul). The
    SYNOPSIS was a 118 line import list followed by every signature, a
    table of contents rather than a synopsis; it is now about forty lines
    that a reader can paste, and every value in it is the measured output
    rather than a placeholder. INSTALLATION is removed, per the rules,
    and README.md keeps the build steps. The EXAMPLES section did not
    compile at all and now runs on both builds.

    The four defects the issue found in the examples, and what each was:

      $addr = addconst($addr,$const)      scalar context stores the
                                          carry, not the sum
      return ($network, $broadcast)       $broadcast never declared,
                                          the local is $bcast
      my $addr = $nip->{addr}             missing semicolon
      my $lastip = $ip-copy()             not Perl; stringification
                                          copies, "$ip"

    plus an unbalanced paren in (undef, $ip->{addr} = addconst(. The wrap
    is now detected with "$ip" lt $before, since the comparison is on the
    string forms rather than the overloaded operators, and the list
    context form of addconst takes the second element. The loop is shown
    wrapping a /30, so the branch is actually exercised:

      step 3: 192.0.2.252/30   wrapped: 1

    A1, shiftleft with no count. Util.pm said "a single shift is
    performed if $n is not specified" and UtilPP.pm said it returns the
    input. UtilPP was right and both builds agree:

      shiftleft($bits128) eq $bits128      yes, on XS and pure Perl

    Both entries now say so, with an example, and note that $n above
    $MAX_SHIFTLEFT croaks.

    A2, naip_gethostbyname documented IPv4 answers as ::FFFF:FFFF:d.d.d.d,
    which is not an address. The answer for 127.0.0.1 is:

      0:0:0:0:0:FFFF:7F00:1

    so the form is ::FFFF:d.d.d.d, the RFC 4291 s2.5.5.2 mapped prefix,
    which is what the function actually produces on both builds.

    A3, three entries wrote ::ffff::d.d.d.d, which has one colon too
    many. Corrected to ::ffff:d.d.d.d, and the isNewIPv4 and isAnyIPv4
    entries now name the prefixes they test, s2.5.5.2 and the union of
    s2.5.5.1 with it.

    A14, "if (hasbits($bits128 & $mask128) {" was missing its closing
    paren here and in UtilPP.pm.

    A16, the EXPORT_OK list omitted seven names that are in @EXPORT_OK:
    AF_INET, AF_INET6, bin2bcdn, bcdn2txt, bcdn2bin, simple_pack and
    comp128. All seven are now listed, the last five under a heading that
    says they are exported for the test suite and are not stable API,
    which is what the code comments about comp128 said all along. The
    import tags are now listed with their real contents, measured by
    importing each into a scratch package, which turned up that :ipv6 is
    :inet without the two IPv4 names and nothing else, and that the
    original list for it was missing four.

    A18, inet_n2ad was documented as returning x:x:x:x:x:x:ddd.ddd.ddd.dd,
    which has a truncated octet. The real form is x:x:x:x:x:x:ddd.ddd.ddd.ddd,
    and inet_n2ad(2001:db8::1) is 2001:DB8:0:0:0:0:0.0.0.1. Two rfc1844
    typos became RFC 4291 s2.2.

    A24, "=item $ipv6naddr = inet_4map6($netaddr or $ipv6naddr" was
    missing its closing paren in the item heading.

    B9, the :noSock6 import tag, which forces havegethostbyname2 to
    report false so the resolver fallback can be tested on a host that
    has Socket6, was undocumented. It has its own section now, labelled
    a test hook. C7's point that there is no single place listing the
    tags that change behaviour is partly answered; the case tags live in
    NetAddr::IP::InetBase and are cross referenced.

    B10, the split between the functions that return undef on bad input
    and the ones that croak on a wrong length, now stated in the
    entries: ipv6_aton, inet_aton and inet_4map6 return undef, while
    hasbits and isIPv4 croak with "Bad arg length ... length is N,
    should be 128". B11's netlimit is a NetAddr::IP function rather than
    one of these, and is left to step 3.

    The RFC 1884 citations become RFC 4291 s2.2 for the accepted forms
    and RFC 5952 s4 for the output, with packzeros documented against
    s4.2.1, s4.2.2 and s4.2.3 separately and an example for each,
    including that a single zero group is never shortened. Table D's
    note that inet_aton short forms are the BSD convention rather than
    RFC 791 is still outstanding; inet_aton('127.1') is 127.0.0.1 and
    inet_aton('192.168.1') is 192.168.0.1, and inet_aton croaks on
    '0x7f.1', so it belongs with a rewritten inet_aton entry.

    Five names for one concept were unified to $bits128 for a 16 byte
    string and $ipv6naddr for an address, per C5, though the full sweep
    across all three function pages is part of finishing this step.

    POD only, no code change. InetBase.pm and UtilPP.pm carry copies of
    several of these entries and are corrected in the commit that
    follows.

    Fix NetAddr::IP::Constants (GH#100, step 1 of the POD overhaul).
    Unindent the item bodies, which rendered as verbatim blocks under
    pod2text, group the constants by the RFC they come from, and drop the
    claim that importing one "ensures that each constant resolves at
    compile time".

    That claim is false and the opposite is worth saying plainly, since
    the constants are read in the hot path of the 128 bit arithmetic.
    They are our variables, so an assignment writes through to the
    module's own copy, which is what the rest of the distribution reads:

      use NetAddr::IP::Constants qw($IPV6_BITS);
      print "$IPV6_BITS\n";                             # 128
      $IPV6_BITS = 999;
      print "$IPV6_BITS\n";                             # 999
      print "$NetAddr::IP::Constants::IPV6_BITS\n";     # 999

    A caller who has already declared a name the import wants is not
    overwritten, because Exporter only installs the alias when the name
    is free, so overriding is reachable and order dependent. InetBase,
    Util and UtilPP each import these and read their own copy, so a
    caller's reassignment changes nothing inside the library. Documented
    as reachable but unsupported rather than as a supported feature.

    One more correction the issue did not list. $MAX_BCD_DIGITS was
    documented as "40 (i.e. ceil(128 * log10(2)))", and that ceiling is
    39, not 40:

      ceil(128*log10(2)) = 39      decimal digits in 2**128 = 39
      bin2bcd of all ones        = 39 digits, unpadded

    40 is right for a different reason. BCD holds one digit per nibble,
    and a packed string has to be a whole number of bytes, so 39 nibbles
    round up to 40, which is the 20 bytes $PACKED_BCD_BYTES holds, and
    simple_pack is what pads to 40 before pack("H40"). The entry now
    gives that reasoning instead of the false equivalence.

    $IPV4_OFFSET gained the two section numbers it covers, RFC 4291
    s2.5.5.1 for the deprecated compatible prefix and s2.5.5.2 for the
    mapped prefix, since both sit at that offset and the entry had only
    the umbrella citation. Table D's note that inet_aton short forms
    such as 127.1 are the BSD convention and not RFC 791 is left for the
    Util.pm commit that rewrites the function entries.

    POD only, no code change. Every example run on both builds.

    Narrow what canon() claims to follow, and document what it does with
    an IPv4 address in the low 32 bits (GH#98). The POD said ipV6 output
    is "as per RFC5952", which overclaims. Sections 4.1 to 4.3 hold:
    leading zeros dropped, the longest run of zero groups shortened to
    ::, the first of two equal runs shortened, lowercase, and canon is
    the lower case of short() on every address tried. Section 5, the
    mixed form for an embedded IPv4 address, is not applied:

      canon ->new('::ffff:192.0.2.1')   ::ffff:c000:201
      canon ->new6FFFF('192.0.2.1')     ::ffff:c000:201
      canon ->new6('1.2.3.4')           ::102:304

    Deferred to a future decision, GH#98, and this entry takes neither
    path. Mixed notation for the mapped prefix alone is the narrowest
    reading of section 5, the one prefix that is both well known and
    current, and is what Python does; the test is isNewIPv4, which is
    what distinguishes the mapped prefix from the compatible one, since
    isIPv4 is also true of ::1 and its mixed form would be ::0.0.0.1.
    It would change canon for mapped addresses and nothing else, leave
    addr, short, full and stringification in hex since none of them
    claims the RFC, and stop canon and short agreeing for those
    addresses, which the POD would then have to say. Mixed notation for
    the compatible prefix as well would agree with glibc, and therefore
    with ipv6_ntoa where Socket6 binds libc, but it would make canon
    stop agreeing with the ::102:304 that new6 documents, and RFC 4291
    deprecates the form. Either way t/114-canon.t gains the mapped cases
    and keeps ::1 and :: unchanged, and anyone comparing stored canon
    strings of mapped addresses sees a new value, so this belongs in the
    series that already changed re, re6 and new(undef).

    A comment at canon() records the section 5 omission where it happens
    and points at GH#98.

    Document that ipv6_ntoa and inet_ntop render an address with an IPv4
    address in the low 32 bits differently depending on Socket6
    (GH#99). inet_ntop is bound to the platform's libc when Socket6 is
    installed and to the module's own _inet_ntop otherwise, and Socket6
    is a recommendation rather than a requirement. Two hosts differing
    only in that one optional module therefore render
    ::ffff:192.0.2.1 as ::ffff:192.0.2.1 and as ::ffff:c000:201. The
    POD said these functions "come from the Socket6 library if it is
    present on this host" without saying what follows from it.

    The table now in the POD is measured, not reasoned. Over 8,040
    addresses, a structured set plus random ones weighted towards zero
    groups, every disagreement between libc and the fallback fell in the
    mapped prefix ::ffff:0:0/96 or the deprecated compatible prefix
    ::/96, and nowhere else. Zero run compression, which of two equal
    runs is shortened, single zero groups, leading zeros and case agree
    throughout, including on 2001:0:0:1:0:0:0:1, where both shorten the
    second run.

    Also correct "takes and IP address" to "an" in the inet_ntop entry.

    POD only. No method of NetAddr::IP or NetAddr::IP::Lite calls either
    function; stringification goes through ipv6_n2x and packzeros, which
    are pure Perl on every host.

    Deferred to a future decision, GH#99. Two ways out, and this entry
    takes neither. Bind inet_ntop to the module's own implementation
    always, and teach the fallback the mixed form for the mapped prefix.
    That makes the text the same on every host, defined by this module
    rather than by whichever libc is underneath, and stops a libc
    rendering it differently from breaking the suite, which is what GH#33
    was. The cost is that on a host with Socket6 today ::192.0.2.1 comes
    back as ::c000:201, so it moves output for existing callers. Or keep
    libc and teach the fallback to match, which moves nothing today but
    leaves the text defined by the host's libc, leaves the GH#33 class of
    failure in place, and forces the compatible prefix to glibc's
    rendering. That is the opposite of Path B of GH#98, so canon and
    ipv6_ntoa would disagree on ::192.0.2.1 unless GH#98 takes the same
    path. Whichever is chosen, the four tests that pin these functions
    should gain the mapped and compatible cases with one expected value
    each, true with and without Socket6.

    A comment at the fallback binding in InetBase.pm now records the
    divergence where the choice is made, and points at GH#99 and GH#21.

    Drop docs/rfc1884.txt (GH#97). The full text of RFC 1884, "IP
    Version 6 Addressing Architecture", December 1995, shipped with
    4.001 in August 2006 and moved to docs/ by 4.004 a fortnight
    later, and nothing has touched it since. It is 37,854 bytes, 3.98%
    of the unpacked distribution, and the only thing under docs/.

    Nothing read it. No POD links to it, no test opened it, no code
    names the path, and the only reference to docs/ anywhere in the
    tree was the skip line in dist.ini that existed to keep the EOL
    test away from it. The generated t/author-eol.t lists 185 files and
    none under docs/, so removing the file and the skip line leaves
    that test at the same 185 files.

    RFC 1884 was obsoleted by RFC 2373 in July 1998, which RFC 3513
    replaced in April 2003, which RFC 4291 replaced in February 2006.
    The addressing architecture is RFC 4291, and the text
    representation rules that :lower and canon() follow are RFC 5952
    from August 2010. Shipping the 1995 text beside code that
    implements the 2006 rules invites a reader to take it for the
    reference.

    The ten mentions of rfc1884 in the POD name the specification, not
    the file, and are unchanged here. They are being replaced with RFC
    4291 and RFC 5952 citations in the POD work.

    The text remains at https://www.rfc-editor.org/rfc/rfc1884 for
    anyone who wants the history.

    Give the shipped Makefile.PL a clean and realclean list again
    (GH#96). The checkout Makefile.PL has listed the generated files
    since 4.079, but header.pl has not, so the shipped one has had no
    list at all since 0da215c, and six files survived make realclean:
    lib/NetAddr/IP/Util.c, lib/NetAddr/IP/Util_IS.pm, xs/config.h,
    xs/config.log, xs/config.status and xs/localperl.h. Pure Perl left
    Util_IS.pm behind.

    The stale xs/config.h was the part that mattered. Configure runs
    only when that file is missing, so the next perl Makefile.PL in the
    same tree reused the old results and never probed again, whatever
    had changed in between.

    Restore the 4.079 split: make clean removes what Makefile.PL
    rewrites on every run, which is Util_IS.pm in both builds and
    localperl.h in the XS build, and make realclean removes the
    configure results. make clean moves the Makefile aside, so
    perl Makefile.PL runs again before the next build and puts those
    three back; the configure results survive until realclean.

    That required dropping the sub clean override from the footer,
    which kept lib/NetAddr/IP/Util.c out of make clean on the grounds
    that "we need this file tracked in git for CPAN distribution". It
    stopped being tracked at 335f5eb, which untracked it, and 4.080_03
    does not ship it, so the override was protecting nothing. The file
    is not needed in the tree either: the postamble regenerates it from
    xs/Util.xs through xsubpp, and a make clean followed by
    perl Makefile.PL and make builds and tests clean.

    The checkout Makefile.PL loses xs/config.h, xs/config.log and
    xs/config.status from its clean list for the same reason, so the
    two copies do not disagree about what a clean build reuses.

    Verified: XS build then make realclean leaves none of the six;
    pure Perl then make realclean leaves none; after make clean,
    Util.c, Util_IS.pm and localperl.h are gone and the three configure
    results are kept; Util.c comes back on the next make, and the next
    perl Makefile.PL --xs after a realclean probes again. Both builds
    161 files and 2535 tests, all pass.

    Correct the :nofqdn example in NetAddr::IP's POD (GH#92). The
    FQDN paragraph under new() told the reader to load NetAddr::IP::Lite,
    which works, since the flag lives there and both modules read it, but
    every other tag example on that page imports through NetAddr::IP and
    a reader of the NetAddr::IP page has no reason to load Lite. Both
    forms set the same $NetAddr::IP::Lite::NoFQDN, checked here, and
    t/124-nofqdn.t already covers the tag arriving through NetAddr::IP.
    POD only.

    Fix LIBS from configure reaching ExtUtils::MakeMaker by the wrong
    name (GH#95). header.pl read xs/config.h and then replaced
    @mm_args[-1], which is depend's hash ref rather than LIBS', so the
    libraries turned depend into an array ref, LIBS stayed empty, and
    EUMM died before writing a Makefile:
        WARNING: depend takes a HASH reference not a ARRAY reference
        Not a HASH reference at ExtUtils/MakeMaker.pm line 837
    Any library configure had to add, which is libnsl or libsocket on
    illumos and older Solaris, was enough to do it. config.h is only
    rewritten when it is missing, so the tree then stayed broken until it
    was deleted by hand. Read the file first and pass the libraries by
    name now.

    Stop emitting the xs/config.h make rule, and stop referring to $begin
    to do it (GH#93). The rule ran xs/configure, a script this
    distribution has not shipped since 4.069, so it could never succeed;
    it only stayed out of the Makefile by accident, because the footer
    referred to $main::begin, which is the package variable of a
    different thing and is always unset. Every build warned
        Name "main::begin" used only once: possible typo
        Use of uninitialized value $begin in concatenation (.) or string
    and then carried on. No perl makes those fatal. The generated
    Makefile.PL enables warnings with a plain "use warnings", which
    [MakeMaker::Awesome] puts there, so both messages printed, the
    Makefile was written and the suite passed, on every perl in the
    matrix. Only a caller that imposes fatal warnings on the whole
    process, as PERL5OPT=-Mwarnings=FATAL does, turns the first one into
    a build that stops.
    Remove the reference and the warnings go; remove the rule and the
    generated Makefile is byte for byte what it was before, and a
    missing xs/config.h stops the build with make's own
        No rule to make target 'xs/config.h', needed by 'Util.c'
    rather than a failed script. The depend entry still lists it as a
    prerequisite. Makefile.PL itself probes configure.gcc, then
    configure.cc, then falls back to pure Perl before writing anything,
    which a make rule cannot repeat.

    Re-enable the Windows test job, pure Perl only, so the runner needs
    no C toolchain. It had been disabled long enough that the reason was
    forgotten, and the reason was three separate things stacked on top of
    each other:
        - the job ran under a POSIX shell, where "perl" is the Cygwin perl
          that Git Bash puts on PATH, and it has no ExtUtils::MakeMaker, so
          the installer reported a core module as missing
        - the flavour of make ExtUtils::MakeMaker writes a Makefile in
          depends on the perl, 5.24 saying "dmake-style" and 5.26 saying
          "gmake-style", and neither make works across the matrix
        - the dependency install did not request the develop phase, which
          the author tests in the distribution need
    It now installs through cpm via the setup action, which also gets all
    five author tests' prerequisites, and asks for gmake explicitly with
    MAKE=gmake so the Makefile flavour does not vary with the perl.

    The Windows job does not set AUTHOR_TESTING, unlike the others. On
    that platform the setup action installs dependencies into
    local/lib/perl5 inside the project directory, and Test::EOF walks the
    working directory, so the check was reading third-party modules and
    failing on Data::Binary's trailing newlines. Test::EOF takes no file
    list and no finder, so it cannot be pointed elsewhere. The five
    author tests skip themselves without the variable. The four release
    tests do not, and still run; they need the develop phase, which is
    still installed, and they pass on Windows.

    Skip local/ in the other line-ending check as well, the one built on
    the EOLFiles finder, for the same reason. Both checks walk the tree
    and neither can be given a file list from dist.ini.

    Verified on Windows, pure Perl, perl 5.24: 160 files and 3676 tests
    with the one failure above, and 2531 with it gone and the author
    tests skipped. t/013-util-binet_pton.t and
    t/025-util-inet_pton.t, which hard-code the output of inet_ntop, both
    pass, so the difference in GH#33 is glibc against BSD and does not
    reach Windows. GH#33 is closed as unreproduced: all forty macOS jobs
    pass, ten perls from 5.24 across four images, with Socket6 built
    into each so libc, not the pure Perl fallback, is under test. The
    tests still assert the rendered string, so a libc rendering these
    three addresses differently would fail them again.

    Stop the SYNOPSIS of both modules importing behaviour-changing tags
    (GH#91). A SYNOPSIS invites pasting, and both lists pulled in every
    tag the module has. Pasted as written, NetAddr::IP's list warned
    twice, for :aton and :rfc3021, and NetAddr::IP::Lite's warned
    once, for :aton. Under "use warnings FATAL => 'all'" both died at
    compile time, in a program that had only asked for Compact and
    Zeros.

    Worse, the tags change behaviour for the whole program rather than
    returning something. A paste of the NetAddr::IP list also switched
    on the legacy Storable and nth() behaviour, and its :lower did
    nothing at all, because import() handles :lower before :upper, so
    :upper wins whichever order they appear in.

    Each list now names functions only. NetAddr::IP points at where
    the tags are documented: :lower, :upper, :old_storable and
    :nofqdn each have a one-line example where they apply, and :aton
    and :rfc3021 are under DEPRECATED. Lite.pm is the smaller module
    and gets no sentence, and its EXPORT_OK drops the tags to match
    NetAddr::IP's, which lists functions only.

    The tags themselves are unchanged and still import as before; this
    is POD only. No test asserted the SYNOPSIS list, and none needed
    changing.

    Verified that each list now loads clean under both plain and FATAL
    warnings, that all twelve tags across the two modules still import,
    and podchecker is clean on both files.

4.080_03  2026-09-30 23:07:41+10:00 Australia/Sydney (TRIAL RELEASE)

    Reformat the test files with perltidy's default profile. Nine of
    them were indented with tabs while the other 140 used spaces, and
    .editorconfig asks for four columns of spaces, so t/ is now
    internally consistent for the first time. Whitespace is the only
    thing that moved, except for four semicolons perltidy deletes by
    default, being ones that are simply empty statements: the one after
    "sub BASE_LEN () { 7 };" in t/043, and one standing before a closing
    brace in each of t/087, t/096 and t/097. None of them changes what
    the code does.

    Tabs survive in six files, inside comments that use them to line up
    columns in a table of test vectors. perltidy does not rewrite comment
    text, which is the right call, so those stay.

    Checked by stripping all whitespace from each file before and after,
    which is the only guarantee perltidy actually makes, so those four
    semicolons are the whole of the difference. The suite passes either
    way: 160 files and 2927 tests from dzil test --all, and 160 files
    and 2531 tests in each of the XS and pure Perl built distributions.

    No .perltidyrc is checked in, so this records the result rather than
    the settings that produced it, and nothing stops the files drifting
    apart again.

    Name an undefined packed argument in the error, instead of warning
    first and then reporting a length of zero. The guards read their
    argument with length() and then did arithmetic or a comparison on
    the result, so an undef reached an operator first and perl warned
    about a value inside the library, at a line the caller cannot act
    on, before the check that names the function could run:
        inet_ntoa(undef)    Use of uninitialized value in numeric eq
                            (==), at InetBase.pm line 332
                          Bad arg length for ...::inet_ntoa, length is
                          should be 4
        hasbits(undef)      Use of uninitialized value in numeric ne
                            (!=), at UtilPP.pm line 137
                          Bad arg length for ...::hasbits, length is 0,
                          should be 128
    Both halves were wrong. The zero described a length nobody passed,
    and inet_ntoa interpolated an empty string because length(undef) is
    the empty string, so its message named the function and the expected
    width but no length at all. The message now says the length is
    undefined, and nothing warns on the way to it.

    Fixed in both implementations, which have to agree: NetAddr::IP::Util
    is native by default and falls back to UtilPP, and the XS half got
    there differently. It declares its arguments as SV *, and SvPV
    turned an undefined argument into an empty string with a length of
    zero without complaining, so it reported the same misleading zero
    and perl's "Use of uninitialized value in subroutine entry" warning
    fired from the caller's line. Each XS function now tests SvOK
    before it calls SvPV.

    inet_ntoa and ipv6_ntoa are pure perl with no XS counterpart, so
    they only needed the guard. ipv6_ntoa was also handing an undefined
    argument to Socket6::inet_ntop, which reported a length of 0 for
    something that had none.

    A wrong but defined length is still measured and reported as before,
    so "ab" still gives 2 and not undefined.

    Fix addition and subtraction accepting a constant that is not a
    number (GH#89). The guard compared $const == int($const), and perl
    numifies both sides first, so a string passed as its leading digits
    or as zero:
        - '5abc' added or subtracted 5
        - '0x10' and '0b11' added 0, which reads as no change at all
    looks_like_number now runs ahead of the guard, and subtraction
    negates only what is a number so the guard sees the original
    otherwise. Hex, binary, 0o and empty strings are rejected. Padded
    and exponent strings, and a Math::BigInt constant, are unaffected.
    The POD in both IP.pm and Lite.pm said only that the constant must
    be an integer, and now says a non-numeric string croaks.

    Keep the documented behaviour for a missing or zero constant, which
    returns a copy. Nothing tested it before, so the new tests pin it:
    undef and the empty string still return a copy for both operators,
    where subtraction previously died inside the negation and addition
    returned a copy.

    Fix both SYNOPSIS use lists, which carried their annotations as qw()
    members, so each module tried to import a symbol named DEPRECATED and
    Lite.pm one named ! as well (GH#83)

    Consolidate the scattered deprecation notes in IP.pm and Lite.pm into a
    DEPRECATED section under EXPORT_OK, and state there that everything
    listed is going in version 5:
        - the promise was only ever attached to a markdown ###### banner in
          a POD verbatim block, and in Lite.pm that sat 58 lines into the
          new_cis6 item body
        - :rfc3021 said only "a future version", and new_cis and new_cis6
          carried no removal version at all
        - :rfc3021, new_cis and new_cis6 are now covered by the promise
    Each item names its replacement. :old_nth is left out, being a
    compatibility switch that has never been marked deprecated and has no
    replacement.

    Warn in the deprecated category when :aton, new_cis or new_cis6 is
    used, naming the replacement in the warning (GH#49). None of the three
    warned before, though all were marked deprecated:
        - :aton warns on import in both IP.pm and Lite.pm
        - new_cis and new_cis6 warn on call; they are defined once in
          Lite.pm and reached from IP.pm via AUTOLOAD
    Behaviour of all three is unchanged, except under use warnings
    FATAL => 'all', where the new warning dies; no warnings 'deprecated'
    silences it. For an import like :aton that silence has to come
    before the use, since the import runs at BEGIN time.

    Require Math::BigInt 1.99, the last release before perl 5.14 (GH#44)

    Remove duplicate NAME section from the Constants.pm POD

    Adjust Constants.pm POD: name each constant with its sigil and
    indent descriptions consistently

    Convert SEE ALSO sections to L<...> links and drop the (3) suffixes

    Uniform code formatting across lib/, following UtilPP.pm:
        - 4 spaces per indent level, no tabs
        - space after commas, my (...) rather than my(...)
        - =item rather than =item *
        - else and elsif on their own line, not cuddled to the brace
    POD is unchanged by the reindent; verbatim examples keep their
    two-space first level.

    Fix {1,3} regex quantifiers broken by a stray space, which had
    disabled the mixed hex/dot-quad branch of InetBase::ipv6_aton and
    the masklen check in coalesce

    Write the shipped Makefile.PL source as inc/MakeMaker/header.pl and
    reapply the style pass there, so the tarball no longer ships the
    old use vars, indent and =item * forms (GH#85)

    Drop AutoLoader from the prerequisites; nothing loads it since GH#70

    Drop vars from the prerequisites; generated Util_IS.pm now declares
    its version with our $VERSION

    Remove the Math::BigInt emulation switch from Lite.pm (GH#84):
        - _force_bi_emu and $no_mbi_emu are gone, and _loadMBI always
          runs the require, so bigint() no longer croaks on a host that
          has Math::BigInt installed
        - drop the stale note on the three known Math::BigInt flavors

    Document the numeric() comparison hazard in the Lite.pm POD: an
    ipV6 value has more digits than a Perl number holds, so ==, <=> and
    sort treat distinct addresses as equal (GH#84)

4.080_02  2026-09-29 17:02:48+10:00 Australia/Sydney (TRIAL RELEASE)

    Fix re6() to support compressed IPv6 addresses (::) and shortened groups (GH#14)

    Fix bcd2bin/bcdn2bin error messages to show correct function name (GH#78)

    Add :all export tag to NetAddr::IP::Constants (GH#81)

    Remove broken _bi_fake fallback in bigint(): Math::BigInt now required
    for bigint() support, added to RuntimeRecommends (GH#44)

    Fix SYNOPSIS in IP.pm and Lite.pm (GH#74 items 3-9):
        - Fix within() example, consolidate my $ip declarations
        - Fix prose indentation, typo "Domanin" -> "Domain"
        - Fix unbalanced parenthesis, fix Zeros/Ones/V4mask/V4net description

    Fix comment in Lite.pm: 0xfffffffe is 2**32 - 2, not 2**32 - 1 (GH#79)

    Fix module load without resolver: replace inet_aton('255.0.0.0') with pack() (GH#69)

    Fix Storable hooks: install at file scope, :old_storable is sticky (GH#8)

    Re-enable tail-call goto dispatches removed in commit 9743c94:
        - IP.pm: splitref/rsplitref -> goto &_splitref
        - UtilPP.pm: addconst/add128/sub128 -> goto &slowadd128
        - UtilPP.pm: bcd2bin -> &_bcdcheck; goto &_bcd2bin
        - UtilPP.pm: bin2bcdn -> goto &_bin2bcdn
        - UtilPP.pm: comp128 restored to return ~ $_[0]

    Convert @ISA + require Exporter to use parent in all modules

    Replace use vars with our declarations, consolidate declaration + init

    Convert tabs to spaces and fix POD indentation in IP.pm and Lite.pm

4.080_01  2026-09-22 09:08:35+10:00 Australia/Sydney (TRIAL RELEASE)

    Validate masklen and number in coalesce, croak on bad arguments (GH#40)

    Fix coalesce on subclass objects (GH#38)

    Fix coalesce to count subnet addresses, not usable hosts (GH#37)

    new6() returns compatible form for IPv4-only hosts, not mapped form (GH#64)

    Add neg and abs overloads with clear error messages (GH#67)

    Anchor bracket notation match to reject text outside brackets (GH#68)

    Fix licence metadata and restore Artistic text (GH#56)

    new6FFFF returns undef on invalid input instead of unblessed hash ref (GH#65)

    BREAKING: re() on IPv6 objects in IPv4 space no longer emits a broken regex (GH#34)

    BREAKING: re6() now returns a non-capturing group (?:...) (GH#50)

    new6() now prefers AAAA over A for dual-stack hostnames, RT#119858 (GH#32)

    Deprecate :rfc3021 tag; hostenum/hostenumref return 2 hosts for /31 and /127 unconditionally (GH#26)

    BREAKING: new(undef) returns undef instead of the default route (GH#29)

    Fix is_local for IPv4 loopback held in IPv6 objects (GH#27)

    Fix pure-Perl _bcdcheck error messages (GH#23)

    Remove dead branch in _splitplan, use named loop variable (GH#18)

    Add BCD boundary input test suite (GH#51)

    Preserve caller $@ and $SIG{__DIE__} on oversized decimal in new() (GH#59)

    Localize $SIG{__DIE__} in module load eval probes, RT#130949 (GH#30)

    Fix POD spelling mistakes: complier, alway, netowrk, occurence, RT#114239 (GH#47)

    Prevent re() from matching addresses embedded in longer dotted strings (GH#35)

    Reject cross-family and non-object arguments in within() and contains() (GH#28)

    Remove faulty _splitplan pre-check that rejected valid short plans (GH#58)

    Fix Compact merging v4 with v6 and mutating arguments (GH#15)

    Fix compactref on subclasses (GH#16)

    Reject bracket-enclosed IPv4 literals (GH#60)

    Assert mode() matches Makefile.PL build choice (GH#61)

    Reject empty string mask in constructor (GH#3)

    Croak on swapped subtraction constant - object (GH#24)

    Fix plus() alias for zero and silent no-op outside 32-bit range (GH#25)

    Detect overflow in decimal integers, return undef in constructor (GH#19)

    Support [addr]/mask URI bracket notation (GH#2)

    Fix _splitplan netlimit pre-check and croak (GH#17)

    Reject non-integer indices in nth() (GH#10)

    Fix 0b/0x literal parsing using oct() instead of string eval (GH#4)

    Reject non-ASCII digits in IP parsing

    Fix version() for large decimal integers, RT#117995 (GH#31)

    Document coalesce() behavior for equal-length masks (GH#45)

    Fix bcdn2bin length check to report digits not bytes (GH#53)

    Make Socket6 an optional recommends, not hard prereq (GH#54)

    Modernize POD: indirect object syntax and RFC 5737 doc addresses

    Bump perl requirement to 5.014 and fix Test2 imports (GH#57)

    Remove Perl 5.10 and 5.12 from CI matrix (GH#57)

    Consolidate sub-distributions into conventional Dist::Zilla layout

    Convert all test files to Test2::V1

    Fix :nofqdn import tag to actually set the flag, RT#111301 (GH#1)

4.079 Fri Mar 25 16:18:26 PDT 2016
    correct non-suppression of leading zeros in certain instances of
    new_no use. Thanks to "Mike Bartman (mbartman)" <mbartman@cisco.com>
    for spotting the bug.

	put in missing code to propagate NetAddr::IP::Lite :nofqdn to IP.pm

4.078 Mon Aug 17 15:35:28 PDT 2015
    fix typo in Util.pm 1.53 MakefilePL that cause compiler to not be
	found at all

4.077 Fri Aug 14 01:17:23 PDT 2015
	re-numbered because of CPAN upload issue

4.076 Thu Aug 13 22:44:48 PDT 2015
	added method is_local() to Lite.pm
	inspired by Xan Charbonne

    fix Util Makefile.PL to accomodate bug in Android's sh

	add method full6m()
	inspired by abraxxa@cpan.org

    fix Util/Makefile.PL issue with clang compiler, bug 86831

4.075 Wed Jun 11 11:41:17 PDT 2014
	make CPAN happy with new rev number

4.074 Wed Jun 11 09:36:10 PDT 2014
	In Lite.pm v1.54,
	change input filter for resolvable hostnames
	to allow the underscore character
	Thanks to grankio [...] gmail.com for the heads up on this issue.

4.073 Sat Apr  5 09:32:11 PDT 2014
	add documentation about FQDN conversion and
	an option to disable

4.072 Mon Jan 27 11:59:58 PST 2014
	modify Makefile.PL to bypass missing 'pod2text'

4.071 Mon Sep 30 13:41:03 PDT 2013
	add method "canon" by request from <tom.jones@bccx.com>

4.070 Thu Sep 12 12:54:22 PDT 2013
	nth documention error fixed. thanks to Anton tobez@tobez.org

	Lite v1.51, add new6FFFF, RFC4291 compliant ipv4->ipV6 new

4.069 Sat May 25 15:10:45 PDT 2013
	In Lite.pm v1.50, add =encoding UTF-8
	In Util.pm v1.50
	changed Makefile.PL to check for config.h when building for XS
	with 'gcc', try building with 'cc', and check again.
	If config.h is not found, force Pure Perl mode.

	Kill XS in winduhs and Darwin, both of which misbehave when compiling XS code

4.068 Wed Apr  3 10:52:24 PDT 2013
	update Makefile.PL in Util.pm v 1.49 to better detect 'winduhs'

4.067 Sat Mar 30 12:57:20 PDT 2013
	Improved diagnostic message for "die" with bad mask for
	hostenum, hostenumref, split, splitref, rsplit, rsplitref
	Thanks to GENSYM@cpan.org for pointing out the need.

4.066 Mon Oct 29 13:30:14 PDT 2012
	update Lite.pm v1.47 to support bracketed IPv6 URI notation
	as described in RFC-3986
	Thanks to Quanah Gibson-Mount mishikal@yahoo.com

4.065 Tue Oct  2 12:36:11 PDT 2012
	correct format for IPv6 embedded IPv4 addresses
	in InetBase v0.8

4.064 Tue Sep 25 13:54:47 PDT 2012
	added support for rfc3021 /31 networks to hostenum

4.063 Fri Aug 10 11:46:18 PDT 2012
	Updated GPL v2.0 text and address in all modules

4.062 Wed Jun  6 12:34:48 PDT 2012
	documentation updates courtesy of
	Ben Bullock <benkasminbullock@gmail.com>
	Thank you Ben.

4.061 Tue May  8 16:24:03 PDT 2012
	fixed bug in Lite v1.44 that returned
	$ip->num() = 2^128 for 0.0.0.0/0
	Thanks to Sebastian <debug@test1.org> for spotting it.

4.060 Fri Apr  6 16:00:02 PDT 2012
	In Lite.pm v1.43,
	fix bug #75976, change in behavior introduced in v4.050
	where an empty string supplied to "new" previously returned
	'undef' and now returns 'default' for ipV4 or ipV6

4.059 Wed Mar  7 12:50:04 PST 2012
	add is_rfc1918 to Lite.pm v1.42

	documentation updates

4.058 Fri Nov 11 19:23:11 PST 2011
	up rev for documentation update
	update documentation in InetBase v0.06

4.057 Fri Nov 11 15:04:20 PST 2011
	Lite.pm v1.40
	add call to InetBase::fillIPv4 to all uses of gethostbyname

	break out the code in InetBase v0.05 that expands short IPv4
	addresses into dotquad format to account for broken BSD
	implementations of inet_aton and gethostbyname that do
	not recognize the short format. EXPORT this as sub 'fillIPv4'

	in Util.pm v1.45, add 'fillIPv4' to calls to gethostbyname to
	work around broken inet_aton and gethostbyname implementations
	in certain BSD implementations

4.056 Wed Nov  2 19:15:31 PDT 2011
	bump rev to incorporate
	improved inet_aton in InetBase v0.04 to overcome broken
	gethostbyname found in NetBSD and OpenBSD

4.055 Fri Oct 28 11:41:22 PDT 2011
	in Lite.pm v1.38
	patch for bug 71869, issues with Math::BigInt varients

4.054 Thu Oct 27 12:48:55 PDT 2011
	In Lite.pm v1.37, remove Calc.pm
	add detection of early Math::Bigint object structure
	fix bug 71869 - a failed test routine

4.053 Wed Oct 26 08:52:34 PDT 2011
	In Lite.pm v1.36
	fix bug #71925. A a sub-varient of #62521 that showed up only for
	short notation for IPv4. i.e. 127/n, 127.0/n, 127.0.0/n but
	not 127.0.0.0/n

4.052 Tue Oct 25 16:18:38 PDT 2011
	add test in Lite.pm v1.35 for api-version of Math::BigInt to
	support versions earlier than 1.70, circa Dec 2003.
	Thanks to Paul Howarth <paul@city-fan.org> for spotting that bug.

4.051 Mon Oct 24 14:44:53 PDT 2011
	fix bug 71869
	in Lite.pm v1.34
	use Math::BigInt::Calc for creating BigInt values and fall
	back to NetAddr::IP::Calc if Math::BigInt is not present.

	remove reference to Config{osname} in InetBase.pm v0.03
	(Util 1.43)


4.050 Sat Oct 22 01:58:57 PDT 2011
	In Lite/Util/lib/NetAddr/IP/Lite/Util/InetBase.pm v0.02
	Socket6 prior to version 0.23 does not have AF_INET6 in the
	EXPORT_OK array, modify InetBase.pm v0.2 to work around this.

	Add support for Math::BigInt to NetAddr::IP::Lite v1.33

4.049 Sat Oct 15 22:15:10 PDT 2011
	Updates to Lite.pm, Util.pm, new module InetBase.pm

	In Lite v1.32
	bug68723, add capability to parse input of the form
	->new6(12345,1). This should have been there but was
	missing. Thanks to Andrei Benea for spotting this.

	In Util v1.41
	add inet_pton, inet_ntop, AF_INET, AF_INET6

	modify inet_n2dx and inet_n2ad to
	recognize the new 128 bit IPv4 format
	::FFFF:FFFF:0:0

	replace isIPv4 with a pure perl version for portablity

	split the following into NetAddr::IP::InetBase v0.01
	to provide better long term support for IPv6
	inet_aton
	inet_ntoa
	ipv6_aton
	ipv6_n2x
	ipv6_n2d
	inet_any2n
	inet_n2dx
	inet_n2ad
	inet_ntop
	inet_pton
	packzeros
	isIPv4
	isNewIPv4
	isAnyIPv4
	AF_INET
	AF_INET6

4.048 Sat Oct  8 01:33:44 PDT 2011
	remove debug print statement from Util v1.40

4.047 Thu Oct  6 23:41:42 PDT 2011
	really correct missing reference in Util v1.39
	doc update only in Lite.pm v1.30

4.046 Thu Oct  6 20:20:33 PDT 2011		DEPRECATED
	corrected missing reference to inet_4map6 in Util v1.38

4.045 Thu Oct  6 18:23:04 PDT 2011		DEPRECATED
	updated NetAddr::IP::Util 1.37
	addid isAnyIPv4, isNewIPv4, inet_4map6
	revised naip_gethostbyname
	to conform to Perl's gethostbyname output

4.044 Wed May 18 14:47:34 PDT 2011
	added missing support for ->compactref(\@list) which is described
	in the documentation but not implemented.

	Thanks to Rusty Bourland codebard@gmail.com for spotting this
	and providing both a patch and test code

4.043 Wed Apr  6 11:31:19 PDT 2011
	Update documentation on the use of "adding constants
	to an IP address".

4.042 Tue Mar 22 15:26:02 PDT 2011
	Update Lite.pm v1.27 to encompass treatment of /31 and /127
	point-to-point networks as described in RFC 3021

	NOTE: for /31's and /127's
	this changes the behavior of the following methods:
		first   returns the "network" address
		last    returns the "broadcast" address
		nth     index 0 returns "network" addr instead of undef
		nth     index 1 returns "broadcast" addr instead of undef
		num     returns 2 instead of 0 (zero)

	"old_nth" behavior is unchanged

	Thanks to Todd Caine todd.caine@gmail.com for pointing this out.

4.041 Tue Mar  8 15:18:16 PST 2011
	Updated Lite.pm v1.26, "sub num" to support usable IP ranges
	greater than 2**32

	Thanks to Jan Ploski jan@plosquare.com for finding this bug

4.040 Sat Feb 19 10:04:00 PST 2011
	correction to use of Util.pm package lexicals

	thanks to mishikal@yahoo.com for spotting the bug and to
	Mark Martinec mark.martinec+ama...@ijs.si for the solution.

4.039 Wed Feb 16 15:48:03 PST 2011
	Correct documentation for 'split' methods

4.038 Fri Dec 17 17:47:47 PST 2010
	Modify subs "new" and "new6" in Lite.pm to accomodate
	Cisco mask syntax that uses space instead of "/" for a separator
	This eliminates the need for "new_cis" and "newcis6" which are now
	deprecated.

	Modify LIte/t/v4-cnew.t and add Lite/t/v6-cnew.t to test the above

4.037 Fri Nov 19 10:48:01 PST 2010
	add :upper and :lower to Lite.pm v1.23
	add comments about rfc5952 requirement for lowercase ipV6 notation
	in Lite.pm v1.23 and IP.pm
	add test for :lower in Lite.pm v1.23

4.036 Tue Nov 16 16:28:37 PST 2010
	In Util.pm v1.35, naip_gethostbyname modified to return undef
	instead of 0 (zero) on failure

	thanks to Terry Cassidy enaudishaylee@tc17.com for the bug report

	In Util.pm v1.35, move sub's ipv6_n2d and ipv6_n2x to non-autosplit
	portion of module to eliminate warnings during autosplit of "our"
	variables

	thanks to Nicholas Bamber <nicholas@periapt.co.uk>
	Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=517361

	In Lite.pm v1.22, update new6 to properly classify short ipv4 notation
	i.e. 127/8 with test for ":" rather than match for \d.\d.\d.\d

	thanks to Steve Huff (SHUFF) * shuff@cpan.org for
	spotting that bug.

	In Lite.pm v1.22, update t/v4-new.t for deprecated array syntax in
	perl 5.13
	was:    qw(...stuff...)
	is:     (qw(...stuff...))

	thanks to Todd Rinaldo <toddr@cpan.org> for reporting this

4.035 Thu Oct 28 14:26:19 PDT 2010
	fix bug in Lite v1.21 where new6 improperly assigns the mask value
	for and ipv4 address in 32 bit space instead of 128 bit space

	Thanks to Mark Martinec and Steve Huff (SHUFF) * shuff@cpan.org
	for spotting and replicating that bug

	added new_cis and new_cis6 to Lite.pm v1.21 to accomodate
	Cisco syntax that has IP and MASK separated by a space.

	Updated typo in documentation that left out example
	print new6 stuff

4.034 Mon Oct 25 16:22:01 PDT 2010
	Updated Lite::_xnew v1.20 to properly handle ipV6 notation of the form
	xxxx:xxxx:xxxx:xxxx:xxxx:xxxx, DDD

	Thanks to Dusty Mabe <Dusty.Mabe@tekelec.com> for spotting this bug

4.033  Wed Sep 29 10:32:50 PDT 2010
	Conditionalize import of AF_INET6 in Util.pm
	NetAddr::IP::UtilPolluted

4.032  Wed Sep 22 13:39:08 PDT 2010
	Added overload => 'ne' and '!=' to Lite.pm v1.18

4.031  Tue Sep 21 19:21:04 PDT 2010
	Pull Socket6 stuff out of Lite 1.17 and put into
	NetAddr::IP::Util.pm 1.33 in its own namespace

4.030  Tue Jul 20 15:32:23 PDT 2010
	Resolve named hosts in Lite.pm using gethostbyname, followed by
	gethostbyname6 to determine whether to set ipV6 flag

	Thanks to Dusty Mabe <Dusty.Mabe@tekelec.com> for spotting this bug

4.029  Thu Jul  8 18:17:38 PDT 2010
	In NetAddr::IP::Lite,
	added support for the sub "new" to resolve host6 names
	if the OPTIONAL perl Socket6 module is available

	Thanks to "Mabe, Dusty" <Dusty.Mabe@tekelec.com> for spotting
	this and suggesting a fix.

4.028  Wed May 12 14:18:20 PDT 2010
	In /Lite/Util/Util.xs v1.32,
	changed netswap() to postincrement
	*a++ = to *a and added increment after save to mollify some
	picky compilers that return possible undefined behavior.

	changed type of _128x10 to 'void'

	Thanks to David Bolt <dbolt@davjam.org> for the above two patches

4.027  Tue Jun  9 10:31:11 PDT 2009
	In NetAddr::IP::Util v1.31,
	ferret out shell value for Makefile.PL when calling
	./configure for systems where the 'x' bit gets lost
	due to bug in Archive::Tar

4.026  Sat Mar  7 16:35:33 PST 2009
	make the compiler test check the environment for
	CC before using Perl's default compiler

4.025  Sat Mar  7 16:15:18 PST 2009
	revised compiler test in Makefile.PL for Util v1.29
	to accomodate picky Solaris "cc"

4.024  Mon Jan 26 00:27:32 PST 2009
	documentation update

4.023  Fri Jan 16 14:30:40 PST 2009
	added the capability to set the CASE of ipV6 text return
	values to either upper or lower. Thanks to
	Rob Riepel <riepel@networking.Stanford.EDU> for developing
	this improvement and providing a comprehensive patch

4.022  Sat Dec 20 13:05:01 PST 2008
  In Util.xs 1.28
	set uninitialized "carry" in XS bin2bcd to zero

	This insidious bug only showed up on 64 bit hosts running perl 5.6.2
	Thanks to Oliver Paukstadt <pstadt@sourcentral.org> for taking the
	time to do the testing for me on his s390 system.

4.021  Wed Dec 10 11:09:36 PST 2008
	Removed test code that produces a warning about all perl versions,
	OOPS!! instead of just the buggy 5.8.0 - 5.8.5 versions.
	Thanks to paul@city-fan.org for reporting this.

4.020  Tue Dec  9 16:25:46 PST 2008
	cleaned up various typo's with good patch from
	Rob Riepel <riepel@networking.Stanford.EDU>
	thanks Rob.

	revised UtilPP v1.7 to work around perl 5.8.4
	failures with certain @_ operations of goto &sub...
	see perl bug [ 23429]. Unfortunately, perl-5.8.4 is
	the distribution of choice for many solaris boxes

4.019  Sat Nov 29 15:15:30 PST 2008
	in Lite/Util, add pure perl testing to XS build

4.018  Fri Nov 28 23:19:01 PST 2008
	revised XS code to be full re-entrant, thread safe in Util.xs v1.26
	removed all traces of mutex locks in Util.xs v1.26
	removed function 'threads' here an in UtilPP v1.6

4.017  Sun Nov 23 19:32:59 PST 2008
	Extended the capability of 'splitref' to allow splitting of
	objects into multiple pieces with differing CIDR masks.
	Returned object list can be split from bottom to top
	or from top to bottom depending on which method is called

		split, rsplit, splitref, rsplitref

	Thanks to kashmish <kashmish@gmail.com> for the idea on
	improving functionality of 'split'.

	Thanks to Rob Riepel <riepel@networking.Stanford.EDU>
	for a faster and more accurate _compV6 function.

  in UtitPP v1.5
	correct documentation error
	add threads reporting (empty string)

  in Util v1.25
	add threads reporting that returns a comma separated
	string of build headers.

	added what is hopefully thread safe operation via
	serialization. Must be invoked by "--with-threads"

  in Lite v1.12
	corrected missing Zeros subroutine
	Zeros and Zero both will work

  in Lite v1.12
	added minus (-) overloading to allow the subtraction
	of two NetAddr::IP objects to get the difference between
	the object->{addr}'s as a numeric value
	Thanks to Rob Riepel <riepel@networking.Stanford.EDU>
	for the initial code and inspiration for this enhancement

4.016  Wed Nov  5 18:13:20 PST 2008
	in Util/ version 1.24
	Clean up Makefile.PL to check actual required link
	libraries against the perl build for consistency

4.015  Sun Nov  2 10:10:38 PST 2008
	in Util v1.23 add missing headers in configure and localconf.h
	for Solaris inet_xton
	thanks to Karl Bunch <karl@digilink.net> for spotting the bug.

4.014  Sat Nov  1 15:13:48 PST 2008
	in Lite.pm v1.11, add test for characters not allowed by
	rfc952 before the call to gethostbyname in sub new() for those
	people that insist on using deprecated functionality :aton
	and OS's that fail to notice calls to gethostbyname with
	binary arguments.

4.013  Wed Oct 22 15:04:49 PDT 2008
	In Lite.pm v1.10, add new no octal method for
	improperly formatted ipV4 addresses

	In Util.pm v1.22, eliminated dependence on PL_sawampersand
	thanks to Mark Martinec <Mark.Martinec@ijs.si>
	for spotting this and submitting a patch.

	In Util.pm v1.22, force -noxs mode for Win32

	In Util.pm v1.22, use autoconf to configure 'C' build

4.012  Thu Oct 16 19:35:33 PDT 2008
	clear build bug for Win32 in Util.pm v 1.21

4.011  released Oct 6 13:10

4.010  Sat Sep 27 17:00:28 PDT 2008
    in NetAddr::IP::Util v0.19
	updated test for ENDIANess in siteconf

	add test in inet_aton to detect overange IP dot quad values
	missed by some broken Socket implementations
	i.e. 256.1.1.1 would fail to return undef

NOTE: 	Versions 4.008 and 4.009 had limited release to tester only
	and were not uploaded to CPAN. All of the v4.008, 4.009
	changes are incorporated in v4.010

4.009  Tue Sep  2 19:09:57 PDT 2008
	In NetAddr::IP::Lite v1.07,
	in the off chance that NetAddr::IP::Lite objects are created
	and the caller later loads NetAddr::IP and expects to use
	those objects, let the AUTOLOAD routine find and redirect
	NetAddr::IP::Lite method and subroutine calls to NetAddr::IP.

	updated Lite/t/v4-wnew.t so that non-existent
	domains are "really" not there

4.008  Sat Jun  7 14:01:55 PDT 2008
	inherit method "new_from_aton" from NetAddr::IP::Lite
	add related documentation

      Inherited methods from Lite.pm updated as follows:

	comparisons of the form <, >, <=, >=
		10.0.0.0/24 {operator} 10.0.0.0/16
	return now return the comparison of the cidr value
	when the address portion is equal.
NOTE:	this comparison returns the comparison of the NUMERIC
	value of the CIDR. This produces the counter intuitive result
	that /24 > /16. There is logic to this, really! For proper
	operation of commands like "Compact" and "Coalesce", lists of
	netaddr objects must sort in ascending order. However, this
	conflicts with the requirement for larger netblocks to sort
	FIRST so as to include smaller ones. This logic extends to
	any requirement for a sort of netaddr objects. It should be
	further noted that the mixing of netaddr objects with varying
	IP addresses and CIDR allocations can lead to unexpected
	results since the comparisons done first on the IP portion
	and then on the CIDR portion. The documentation has been
	updated appropriately.
	Thanks to Peter DeVries for spotting this discrepancy

4.007  Wed Jun  6 16:41:11 VET 2007
       Update copyright dates

4.006  Wed Jun  6 15:58:04 VET 2007

       A patch from Michael got rid of $& and $` as reported by Daryl
       O'Shea and documented at
       http://issues.apache.org/SpamAssassin/show_bug.cgi?id=5312

4.004  Wed Aug 16 16:01:54 PDT 2006
	update to include/exclude files in corrupted distro

4.003  Sun Aug  6 10:48:25 PDT 2006
	correct SYNOPSIS documentation
	add :old_nth

	update Lite.pm documentation
	update Util.pm documentation
	Imported into distribution CVS tree - Some revision number
	mismatches are to be expected
	Latin-1 is back
	Fixed some angle brackets so that they show up in the docs

4.002  Fri Aug  4 14:14:16 PDT 2006
	remove unused global variable $isV6

	update Lite.pm to v1.02
	$isV6 global converted to a lexical variable within sub "_xnew"
	$Class global removed and replaced by calls to UNIVERSAL::isa
	Thanks to julian@mehnle.net for spotting problems related to
	using the Lite.pm with mod_perl

4.001  Thu Jul  6 14:09:01 PDT 2006
	various bug fixes courtesy of Luis Munoz:
	changes to Lite.pm v1.01, Util.pm v0.17 see Changes in those distros.
	update t/v6-re.t, addconst called as a scalar, should be called to
	return the address value ()[1]

4.000  Mon Jun 19 21:51:10 PDT 2006
	initial release of version 4.000 which includes
	full support of ipV6 addresses and drops the requirement
	for Math::BigInt and will run on older versions of Perl
	at least back to  5.005_03

