netdata/netdata

View on GitHub
src/libnetdata/libjudy/src/JudyL/JudyLPrev.c

Summary

Maintainability
Test Coverage
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
//
// This program is free software; you can redistribute it and/or modify it
// under the term of the GNU Lesser General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your
// option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
// for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
// _________________

// @(#) $Revision: 4.54 $ $Source: /judy/src/JudyCommon/JudyPrevNext.c $
//
// Judy*Prev() and Judy*Next() functions for Judy1 and JudyL.
// Compile with one of -DJUDY1 or -DJUDYL.
//
// Compile with -DJUDYNEXT for the Judy*Next() function; otherwise defaults to
// Judy*Prev().

#if (! (defined(JUDY1) || defined(JUDYL)))
#error:  One of -DJUDY1 or -DJUDYL must be specified.
#endif

#ifndef JUDYNEXT
#ifndef JUDYPREV
#define    JUDYPREV 1        // neither set => use default.
#endif
#endif

#ifdef JUDY1
#include "Judy1.h"
#else
#include "JudyL.h"
#endif

#include "JudyPrivate1L.h"


// ****************************************************************************
// J U D Y   1   P R E V
// J U D Y   1   N E X T
// J U D Y   L   P R E V
// J U D Y   L   N E X T
//
// See the manual entry for the API.
//
// OVERVIEW OF Judy*Prev():
//
// Use a reentrant switch statement (state machine, SM1 = "get") to decode the
// callers *PIndex-1, starting with the (PArray), through branches, if
// any, down to an immediate or a leaf.  Look for *PIndex-1 in that leaf, and
// if found, return it.
//
// A dead end is either a branch that does not contain a JP for the appropriate
// digit in *PIndex-1, or a leaf that does not contain the undecoded digits of
// *PIndex-1.  Upon reaching a dead end, backtrack through the leaf/branches
// that were just traversed, using a list (history) of parent JPs that is built
// while going forward in SM1Get.  Start with the current leaf or branch.  In a
// backtracked leaf, look for an Index less than *PIndex-1.  In each
// backtracked branch, look "sideways" for the next JP, if any, lower than the
// one for the digit (from *PIndex-1) that was previously decoded.  While
// backtracking, if a leaf has no previous Index or a branch has no lower JP,
// go to its parent branch in turn.  Upon reaching the JRP, return failure, "no
// previous Index".  The backtrack process is sufficiently different from
// SM1Get to merit its own separate reentrant switch statement (SM2 =
// "backtrack").
//
// While backtracking, upon finding a lower JP in a branch, there is certain to
// be a "prev" Index under that JP (unless the Judy array is corrupt).
// Traverse forward again, this time taking the last (highest, right-most) JP
// in each branch, and the last (highest) Index upon reaching an immediate or a
// leaf.  This traversal is sufficiently different from SM1Get and SM2Backtrack
// to merit its own separate reentrant switch statement (SM3 = "findlimit").
//
// "Decode" bytes in JPs complicate this process a little.  In SM1Get, when a
// JP is a narrow pointer, that is, when states are skipped (so the skipped
// digits are stored in jp_DcdPopO), compare the relevant digits to the same
// digits in *PIndex-1.  If they are EQUAL, proceed in SM1Get as before.  If
// jp_DcdPopOs digits are GREATER, treat the JP as a dead end and proceed in
// SM2Backtrack.  If jp_DcdPopOs digits are LESS, treat the JP as if it had
// just been found during a backtrack and proceed directly in SM3Findlimit.
//
// Note that Decode bytes can be ignored in SM3Findlimit; they dont matter.
// Also note that in practice the Decode bytes are routinely compared with
// *PIndex-1 because thats simpler and no slower than first testing for
// narrowness.
//
// Decode bytes also make it unnecessary to construct the Index to return (the
// revised *PIndex) during the search.  This step is deferred until finding an
// Index during backtrack or findlimit, before returning it.  The first digit
// of *PIndex is derived (saved) based on which JP is used in a JRP branch.
// The remaining digits are obtained from the jp_DcdPopO field in the JP (if
// any) above the immediate or leaf containing the found (prev) Index, plus the
// remaining digit(s) in the immediate or leaf itself.  In the case of a LEAFW,
// the Index to return is found directly in the leaf.
//
// Note:  Theoretically, as described above, upon reaching a dead end, SM1Get
// passes control to SM2Backtrack to look sideways, even in a leaf.  Actually
// its a little more efficient for the SM1Get leaf cases to shortcut this and
// take care of the sideways searches themselves.  Hence the history list only
// contains branch JPs, and SM2Backtrack only handles branches.  In fact, even
// the branch handling cases in SM1Get do some shortcutting (sideways
// searching) to avoid pushing history and calling SM2Backtrack unnecessarily.
//
// Upon reaching an Index to return after backtracking, *PIndex must be
// modified to the found Index.  In principle this could be done by building
// the Index from a saved rootdigit (in the top branch) plus the Dcd bytes from
// the parent JP plus the appropriate Index bytes from the leaf.  However,
// Immediates are difficult because their parent JPs lack one (last) digit.  So
// instead just build the *PIndex to return "top down" while backtracking and
// findlimiting.
//
// This function is written iteratively for speed, rather than recursively.
//
// CAVEATS:
//
// Why use a backtrack list (history stack), since it has finite size?  The
// size is small for Judy on both 32-bit and 64-bit systems, and a list (really
// just an array) is fast to maintain and use.  Other alternatives include
// doing a lookahead (lookaside) in each branch while traversing forward
// (decoding), and restarting from the top upon a dead end.
//
// A lookahead means noting the last branch traversed which contained a
// non-null JP lower than the one specified by a digit in *PIndex-1, and
// returning to that point for SM3Findlimit.  This seems like a good idea, and
// should be pretty cheap for linear and bitmap branches, but it could result
// in up to 31 unnecessary additional cache line fills (in extreme cases) for
// every uncompressed branch traversed.  We have considered means of attaching
// to or hiding within an uncompressed branch (in null JPs) a "cache line map"
// or other structure, such as an offset to the next non-null JP, that would
// speed this up, but it seems unnecessary merely to avoid having a
// finite-length list (array).  (If JudySL is ever made "native", the finite
// list length will be an issue.)
//
// Restarting at the top of the Judy array after a dead end requires a careful
// modification of *PIndex-1 to decrement the digit for the parent branch and
// set the remaining lower digits to all 1s.  This must be repeated each time a
// parent branch contains another dead end, so even though it should all happen
// in cache, the CPU time can be excessive.  (For JudySL or an equivalent
// "infinitely deep" Judy array, consider a hybrid of a large, finite,
// "circular" list and a restart-at-top when the list is backtracked to
// exhaustion.)
//
// Why search for *PIndex-1 instead of *PIndex during SM1Get?  In rare
// instances this prevents an unnecessary decode down the wrong path followed
// by a backtrack; its pretty cheap to set up initially; and it means the
// SM1Get machine can simply return if/when it finds that Index.
//
// TBD:  Wed like to enhance this function to make successive searches faster.
// This would require saving some previous state, including the previous Index
// returned, and in which leaf it was found.  If the next call is for the same
// Index and the array has not been modified, start at the same leaf.  This
// should be much easier to implement since this is iterative rather than
// recursive code.
//
// VARIATIONS FOR Judy*Next():
//
// The Judy*Next() code is nearly a perfect mirror of the Judy*Prev() code.
// See the Judy*Prev() overview comments, and mentally switch the following:
//
// - "*PIndex-1"  => "*PIndex+1"
// - "less than"  => "greater than"
// - "lower"      => "higher"
// - "lowest"     => "highest"
// - "next-left"  => "next-right"
// - "right-most" => "left-most"
//
// Note:  SM3Findlimit could be called SM3Findmax/SM3Findmin, but a common name
// for both Prev and Next means many fewer ifdefs in this code.
//
// TBD:  Currently this code traverses a JP whether its expanse is partially or
// completely full (populated).  For Judy1 (only), since there is no value area
// needed, consider shortcutting to a "success" return upon encountering a full
// JP in SM1Get (or even SM3Findlimit?)  A full JP looks like this:
//
//    (((JU_JPDCDPOP0(Pjp) ^ cJU_ALLONES) & cJU_POP0MASK(cLevel)) == 0)

#ifdef JUDY1
#ifdef JUDYPREV
FUNCTION int Judy1Prev
#else
FUNCTION int Judy1Next
#endif
#else
#ifdef JUDYPREV
FUNCTION PPvoid_t JudyLPrev
#else
FUNCTION PPvoid_t JudyLNext
#endif
#endif
        (
    Pcvoid_t  PArray,    // Judy array to search.
    Word_t *  PIndex,    // starting point and result.
    PJError_t PJError    // optional, for returning error info.
        )
{
    Pjp_t      Pjp, Pjp2;    // current JPs.
    Pjbl_t      Pjbl;        // Pjp->jp_Addr masked and cast to types:
    Pjbb_t      Pjbb;
    Pjbu_t      Pjbu;

// Note:  The following initialization is not strictly required but it makes
// gcc -Wall happy because there is an "impossible" path from Immed handling to
// SM1LeafLImm code that looks like Pjll might be used before set:

    Pjll_t      Pjll = (Pjll_t) NULL;
    Word_t      state;    // current state in SM.
    Word_t      digit;    // next digit to decode from Index.

// Note:  The following initialization is not strictly required but it makes
// gcc -Wall happy because there is an "impossible" path from Immed handling to
// SM1LeafLImm code (for JudyL & JudyPrev only) that looks like pop1 might be
// used before set:

#if (defined(JUDYL) && defined(JUDYPREV))
    Word_t      pop1 = 0;    // in a leaf.
#else
    Word_t      pop1;        // in a leaf.
#endif
    int      offset;    // linear branch/leaf, from j__udySearchLeaf*().
    int      subexp;    // subexpanse in a bitmap branch.
    Word_t      bitposmask;    // bit in bitmap for Index.

// History for SM2Backtrack:
//
// For a given histnum, APjphist[histnum] is a parent JP that points to a
// branch, and Aoffhist[histnum] is the offset of the NEXT JP in the branch to
// which the parent JP points.  The meaning of Aoffhist[histnum] depends on the
// type of branch to which the parent JP points:
//
// Linear:  Offset of the next JP in the JP list.
//
// Bitmap:  Which subexpanse, plus the offset of the next JP in the
// subexpanses JP list (to avoid bit-counting again), plus for Judy*Next(),
// hidden one byte to the left, which digit, because Judy*Next() also needs
// this.
//
// Uncompressed:  Digit, which is actually the offset of the JP in the branch.
//
// Note:  Only branch JPs are stored in APjphist[] because, as explained
// earlier, SM1Get shortcuts sideways searches in leaves (and even in branches
// in some cases), so SM2Backtrack only handles branches.

#define    HISTNUMMAX cJU_ROOTSTATE    // maximum branches traversable.
    Pjp_t    APjphist[HISTNUMMAX];    // list of branch JPs traversed.
    int    Aoffhist[HISTNUMMAX];    // list of next JP offsets; see above.
    int    histnum = 0;        // number of JPs now in list.


// ----------------------------------------------------------------------------
// M A C R O S
//
// These are intended to make the code a bit more readable and less redundant.


// "PUSH" AND "POP" Pjp AND offset ON HISTORY STACKS:
//
// Note:  Ensure a corrupt Judy array does not overflow *hist[].  Meanwhile,
// underflowing *hist[] simply means theres no more room to backtrack =>
// "no previous/next Index".

#define    HISTPUSH(Pjp,Offset)            \
    APjphist[histnum] = (Pjp);        \
    Aoffhist[histnum] = (Offset);        \
                        \
    if (++histnum >= HISTNUMMAX)        \
    {                    \
        JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT) \
        JUDY1CODE(return(JERRI );)        \
        JUDYLCODE(return(PPJERR);)        \
    }

#define    HISTPOP(Pjp,Offset)            \
    if ((histnum--) < 1) JU_RET_NOTFOUND;    \
    (Pjp)     = APjphist[histnum];        \
    (Offset) = Aoffhist[histnum]

// How to pack/unpack Aoffhist[] values for bitmap branches:

#ifdef JUDYPREV

#define    HISTPUSHBOFF(Subexp,Offset,Digit)      \
    (((Subexp) * cJU_BITSPERSUBEXPB) | (Offset))

#define    HISTPOPBOFF(Subexp,Offset,Digit)      \
    (Subexp)  = (Offset) / cJU_BITSPERSUBEXPB; \
    (Offset) %= cJU_BITSPERSUBEXPB
#else

#define    HISTPUSHBOFF(Subexp,Offset,Digit)     \
     (((Digit) << cJU_BITSPERBYTE)         \
    | ((Subexp) * cJU_BITSPERSUBEXPB) | (Offset))

#define    HISTPOPBOFF(Subexp,Offset,Digit)     \
    (Digit)   = (Offset) >> cJU_BITSPERBYTE; \
    (Subexp)  = ((Offset) & JU_LEASTBYTESMASK(1)) / cJU_BITSPERSUBEXPB; \
    (Offset) %= cJU_BITSPERSUBEXPB
#endif


// CHECK FOR NULL JP:

#define    JPNULL(Type)  (((Type) >= cJU_JPNULL1) && ((Type) <= cJU_JPNULLMAX))


// SEARCH A BITMAP:
//
// This is a weak analog of j__udySearchLeaf*() for bitmaps.  Return the actual
// or next-left position, base 0, of Digit in the single uint32_t bitmap, also
// given a Bitposmask for Digit.
//
// Unlike j__udySearchLeaf*(), the offset is not returned bit-complemented if
// Digits bit is unset, because the caller can check the bitmap themselves to
// determine that.  Also, if Digits bit is unset, the returned offset is to
// the next-left JP (including -1), not to the "ideal" position for the Index =
// next-right JP.
//
// Shortcut and skip calling j__udyCountBits*() if the bitmap is full, in which
// case (Digit % cJU_BITSPERSUBEXP*) itself is the base-0 offset.
//
// TBD for Judy*Next():  Should this return next-right instead of next-left?
// That is, +1 from current value?  Maybe not, if Digits bit IS set, +1 would
// be wrong.

#define    SEARCHBITMAPB(Bitmap,Digit,Bitposmask)                \
    (((Bitmap) == cJU_FULLBITMAPB) ? (Digit % cJU_BITSPERSUBEXPB) :    \
     j__udyCountBitsB((Bitmap) & JU_MASKLOWERINC(Bitposmask)) - 1)

#define    SEARCHBITMAPL(Bitmap,Digit,Bitposmask)                \
    (((Bitmap) == cJU_FULLBITMAPL) ? (Digit % cJU_BITSPERSUBEXPL) :    \
     j__udyCountBitsL((Bitmap) & JU_MASKLOWERINC(Bitposmask)) - 1)

#ifdef JUDYPREV
// Equivalent to search for the highest offset in Bitmap:

#define    SEARCHBITMAPMAXB(Bitmap)                  \
    (((Bitmap) == cJU_FULLBITMAPB) ? cJU_BITSPERSUBEXPB - 1 : \
     j__udyCountBitsB(Bitmap) - 1)

#define    SEARCHBITMAPMAXL(Bitmap)                  \
    (((Bitmap) == cJU_FULLBITMAPL) ? cJU_BITSPERSUBEXPL - 1 : \
     j__udyCountBitsL(Bitmap) - 1)
#endif


// CHECK DECODE BYTES:
//
// Check Decode bytes in a JP against the equivalent portion of *PIndex.  If
// *PIndex is lower (for Judy*Prev()) or higher (for Judy*Next()), this JP is a
// dead end (the same as if it had been absent in a linear or bitmap branch or
// null in an uncompressed branch), enter SM2Backtrack; otherwise enter
// SM3Findlimit to find the highest/lowest Index under this JP, as if the code
// had already backtracked to this JP.

#ifdef JUDYPREV
#define    CDcmp__ <
#else
#define    CDcmp__ >
#endif

#define    CHECKDCD(cState)                        \
    if (JU_DCDNOTMATCHINDEX(*PIndex, Pjp, cState))                    \
    {                                \
        if ((*PIndex        & cJU_DCDMASK(cState))        \
          CDcmp__(JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(cState)))        \
        {                                \
        goto SM2Backtrack;                    \
        }                                \
        goto SM3Findlimit;                        \
    }


// PREPARE TO HANDLE A LEAFW OR JRP BRANCH IN SM1:
//
// Extract a state-dependent digit from Index in a "constant" way, then jump to
// common code for multiple cases.

#define    SM1PREPB(cState,Next)                \
    state = (cState);                \
    digit = JU_DIGITATSTATE(*PIndex, cState);    \
    goto Next


// PREPARE TO HANDLE A LEAFW OR JRP BRANCH IN SM3:
//
// Optionally save Dcd bytes into *PIndex, then save state and jump to common
// code for multiple cases.

#define    SM3PREPB_DCD(cState,Next)            \
    JU_SETDCD(*PIndex, Pjp, cState);            \
    SM3PREPB(cState,Next)

#define    SM3PREPB(cState,Next)  state = (cState); goto Next


// ----------------------------------------------------------------------------
// CHECK FOR SHORTCUTS:
//
// Error out if PIndex is null.  Execute JU_RET_NOTFOUND if the Judy array is
// empty or *PIndex is already the minimum/maximum Index possible.
//
// Note:  As documented, in case of failure *PIndex may be modified.

    if (PIndex == (PWord_t) NULL)
    {
        JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX);
        JUDY1CODE(return(JERRI );)
        JUDYLCODE(return(PPJERR);)
    }

#ifdef JUDYPREV
    if ((PArray == (Pvoid_t) NULL) || ((*PIndex)-- == 0))
#else
    if ((PArray == (Pvoid_t) NULL) || ((*PIndex)++ == cJU_ALLONES))
#endif
        JU_RET_NOTFOUND;


// HANDLE JRP:
//
// Before even entering SM1Get, check the JRP type.  For JRP branches, traverse
// the JPM; handle LEAFW leaves directly; but look for the most common cases
// first.

// ROOT-STATE LEAF that starts with a Pop0 word; just look within the leaf:
//
// If *PIndex is in the leaf, return it; otherwise return the Index, if any,
// below where it would belong.

    if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
    {
        Pjlw_t Pjlw = P_JLW(PArray);    // first word of leaf.
        pop1 = Pjlw[0] + 1;

        if ((offset = j__udySearchLeafW(Pjlw + 1, pop1, *PIndex))
        >= 0)                // Index is present.
        {
        assert(offset < pop1);              // in expected range.
        JU_RET_FOUND_LEAFW(Pjlw, pop1, offset); // *PIndex is set.
        }

#ifdef JUDYPREV
        if ((offset = ~offset) == 0)    // no next-left Index.
#else
        if ((offset = ~offset) >= pop1)    // no next-right Index.
#endif
        JU_RET_NOTFOUND;

        assert(offset <= pop1);        // valid result.

#ifdef JUDYPREV
        *PIndex = Pjlw[offset--];        // next-left Index, base 1.
#else
        *PIndex = Pjlw[offset + 1];        // next-right Index, base 1.
#endif
        JU_RET_FOUND_LEAFW(Pjlw, pop1, offset);    // base 0.

    }
    else    // JRP BRANCH
    {
        Pjpm_t Pjpm = P_JPM(PArray);
        Pjp = &(Pjpm->jpm_JP);

//        goto SM1Get;
    }

// ============================================================================
// STATE MACHINE 1 -- GET INDEX:
//
// Search for *PIndex (already decremented/incremented so as to be inclusive).
// If found, return it.  Otherwise in theory hand off to SM2Backtrack or
// SM3Findlimit, but in practice "shortcut" by first sideways searching the
// current branch or leaf upon hitting a dead end.  During sideways search,
// modify *PIndex to a new path taken.
//
// ENTRY:  Pjp points to next JP to interpret, whose Decode bytes have not yet
// been checked.  This JP is not yet listed in history.
//
// Note:  Check Decode bytes at the start of each loop, not after looking up a
// new JP, so its easy to do constant shifts/masks, although this requires
// cautious handling of Pjp, offset, and *hist[] for correct entry to
// SM2Backtrack.
//
// EXIT:  Return, or branch to SM2Backtrack or SM3Findlimit with correct
// interface, as described elsewhere.
//
// WARNING:  For run-time efficiency the following cases replicate code with
// varying constants, rather than using common code with variable values!

SM1Get:                // return here for next branch/leaf.

    switch (JU_JPTYPE(Pjp))
    {


// ----------------------------------------------------------------------------
// LINEAR BRANCH:
//
// Check Decode bytes, if any, in the current JP, then search for a JP for the
// next digit in *PIndex.

    case cJU_JPBRANCH_L2: CHECKDCD(2); SM1PREPB(2, SM1BranchL);
    case cJU_JPBRANCH_L3: CHECKDCD(3); SM1PREPB(3, SM1BranchL);
#ifdef JU_64BIT
    case cJU_JPBRANCH_L4: CHECKDCD(4); SM1PREPB(4, SM1BranchL);
    case cJU_JPBRANCH_L5: CHECKDCD(5); SM1PREPB(5, SM1BranchL);
    case cJU_JPBRANCH_L6: CHECKDCD(6); SM1PREPB(6, SM1BranchL);
    case cJU_JPBRANCH_L7: CHECKDCD(7); SM1PREPB(7, SM1BranchL);
#endif
    case cJU_JPBRANCH_L:           SM1PREPB(cJU_ROOTSTATE, SM1BranchL);

// Common code (state-independent) for all cases of linear branches:

SM1BranchL:
        Pjbl = P_JBL(Pjp->jp_Addr);

// Found JP matching current digit in *PIndex; record parent JP and the next
// JPs offset, and iterate to the next JP:

        if ((offset = j__udySearchLeaf1((Pjll_t) (Pjbl->jbl_Expanse),
                         Pjbl->jbl_NumJPs, digit)) >= 0)
        {
        HISTPUSH(Pjp, offset);
        Pjp = (Pjbl->jbl_jp) + offset;
        goto SM1Get;
        }

// Dead end, no JP in BranchL for next digit in *PIndex:
//
// Get the ideal location of digits JP, and if theres no next-left/right JP
// in the BranchL, shortcut and start backtracking one level up; ignore the
// current Pjp because it points to a BranchL with no next-left/right JP.

#ifdef JUDYPREV
        if ((offset = (~offset) - 1) < 0)    // no next-left JP in BranchL.
#else
        if ((offset = (~offset)) >= Pjbl->jbl_NumJPs)  // no next-right.
#endif
        goto SM2Backtrack;

// Theres a next-left/right JP in the current BranchL; save its digit in
// *PIndex and shortcut to SM3Findlimit:

        JU_SETDIGIT(*PIndex, Pjbl->jbl_Expanse[offset], state);
        Pjp = (Pjbl->jbl_jp) + offset;
        goto SM3Findlimit;


// ----------------------------------------------------------------------------
// BITMAP BRANCH:
//
// Check Decode bytes, if any, in the current JP, then look for a JP for the
// next digit in *PIndex.

    case cJU_JPBRANCH_B2: CHECKDCD(2); SM1PREPB(2, SM1BranchB);
    case cJU_JPBRANCH_B3: CHECKDCD(3); SM1PREPB(3, SM1BranchB);
#ifdef JU_64BIT
    case cJU_JPBRANCH_B4: CHECKDCD(4); SM1PREPB(4, SM1BranchB);
    case cJU_JPBRANCH_B5: CHECKDCD(5); SM1PREPB(5, SM1BranchB);
    case cJU_JPBRANCH_B6: CHECKDCD(6); SM1PREPB(6, SM1BranchB);
    case cJU_JPBRANCH_B7: CHECKDCD(7); SM1PREPB(7, SM1BranchB);
#endif
    case cJU_JPBRANCH_B:           SM1PREPB(cJU_ROOTSTATE, SM1BranchB);

// Common code (state-independent) for all cases of bitmap branches:

SM1BranchB:
        Pjbb = P_JBB(Pjp->jp_Addr);

// Locate the digits JP in the subexpanse list, if present, otherwise the
// offset of the next-left JP, if any:

        subexp     = digit / cJU_BITSPERSUBEXPB;
        assert(subexp < cJU_NUMSUBEXPB);    // falls in expected range.
        bitposmask = JU_BITPOSMASKB(digit);
        offset     = SEARCHBITMAPB(JU_JBB_BITMAP(Pjbb, subexp), digit,
                       bitposmask);
        // right range:
        assert((offset >= -1) && (offset < (int) cJU_BITSPERSUBEXPB));

// Found JP matching current digit in *PIndex:
//
// Record the parent JP and the next JPs offset; and iterate to the next JP.

//        if (JU_BITMAPTESTB(Pjbb, digit))            // slower.
        if (JU_JBB_BITMAP(Pjbb, subexp) & bitposmask)    // faster.
        {
        // not negative since at least one bit is set:
        assert(offset >= 0);

        HISTPUSH(Pjp, HISTPUSHBOFF(subexp, offset, digit));

        if ((Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp))) == (Pjp_t) NULL)
        {
            JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
            JUDY1CODE(return(JERRI );)
            JUDYLCODE(return(PPJERR);)
        }

        Pjp += offset;
        goto SM1Get;        // iterate to next JP.
        }

// Dead end, no JP in BranchB for next digit in *PIndex:
//
// If theres a next-left/right JP in the current BranchB, shortcut to
// SM3Findlimit.  Note:  offset is already set to the correct value for the
// next-left/right JP.

#ifdef JUDYPREV
        if (offset >= 0)        // next-left JP is in this subexpanse.
        goto SM1BranchBFindlimit;

        while (--subexp >= 0)        // search next-left subexpanses.
#else
        if (JU_JBB_BITMAP(Pjbb, subexp) & JU_MASKHIGHEREXC(bitposmask))
        {
        ++offset;            // next-left => next-right.
        goto SM1BranchBFindlimit;
        }

        while (++subexp < cJU_NUMSUBEXPB)    // search next-right subexps.
#endif
        {
        if (! JU_JBB_PJP(Pjbb, subexp)) continue;  // empty subexpanse.

#ifdef JUDYPREV
        offset = SEARCHBITMAPMAXB(JU_JBB_BITMAP(Pjbb, subexp));
        // expected range:
        assert((offset >= 0) && (offset < cJU_BITSPERSUBEXPB));
#else
        offset = 0;
#endif

// Save the next-left/right JPs digit in *PIndex:

SM1BranchBFindlimit:
        JU_BITMAPDIGITB(digit, subexp, JU_JBB_BITMAP(Pjbb, subexp),
                offset);
        JU_SETDIGIT(*PIndex, digit, state);

        if ((Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp))) == (Pjp_t) NULL)
        {
            JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
            JUDY1CODE(return(JERRI );)
            JUDYLCODE(return(PPJERR);)
        }

        Pjp += offset;
        goto SM3Findlimit;
        }

// Theres no next-left/right JP in the BranchB:
//
// Shortcut and start backtracking one level up; ignore the current Pjp because
// it points to a BranchB with no next-left/right JP.

        goto SM2Backtrack;


// ----------------------------------------------------------------------------
// UNCOMPRESSED BRANCH:
//
// Check Decode bytes, if any, in the current JP, then look for a JP for the
// next digit in *PIndex.

    case cJU_JPBRANCH_U2: CHECKDCD(2); SM1PREPB(2, SM1BranchU);
    case cJU_JPBRANCH_U3: CHECKDCD(3); SM1PREPB(3, SM1BranchU);
#ifdef JU_64BIT
    case cJU_JPBRANCH_U4: CHECKDCD(4); SM1PREPB(4, SM1BranchU);
    case cJU_JPBRANCH_U5: CHECKDCD(5); SM1PREPB(5, SM1BranchU);
    case cJU_JPBRANCH_U6: CHECKDCD(6); SM1PREPB(6, SM1BranchU);
    case cJU_JPBRANCH_U7: CHECKDCD(7); SM1PREPB(7, SM1BranchU);
#endif
    case cJU_JPBRANCH_U:           SM1PREPB(cJU_ROOTSTATE, SM1BranchU);

// Common code (state-independent) for all cases of uncompressed branches:

SM1BranchU:
        Pjbu = P_JBU(Pjp->jp_Addr);
        Pjp2 = (Pjbu->jbu_jp) + digit;

// Found JP matching current digit in *PIndex:
//
// Record the parent JP and the next JPs digit, and iterate to the next JP.
//
// TBD:  Instead of this, just goto SM1Get, and add cJU_JPNULL* cases to the
// SM1Get state machine?  Then backtrack?  However, it means you cant detect
// an inappropriate cJU_JPNULL*, when it occurs in other than a BranchU, and
// return JU_RET_CORRUPT.

        if (! JPNULL(JU_JPTYPE(Pjp2)))    // digit has a JP.
        {
        HISTPUSH(Pjp, digit);
        Pjp = Pjp2;
        goto SM1Get;
        }

// Dead end, no JP in BranchU for next digit in *PIndex:
//
// Search for a next-left/right JP in the current BranchU, and if one is found,
// save its digit in *PIndex and shortcut to SM3Findlimit:

#ifdef JUDYPREV
        while (digit >= 1)
        {
        Pjp = (Pjbu->jbu_jp) + (--digit);
#else
        while (digit < cJU_BRANCHUNUMJPS - 1)
        {
        Pjp = (Pjbu->jbu_jp) + (++digit);
#endif
        if (JPNULL(JU_JPTYPE(Pjp))) continue;

        JU_SETDIGIT(*PIndex, digit, state);
        goto SM3Findlimit;
        }

// Theres no next-left/right JP in the BranchU:
//
// Shortcut and start backtracking one level up; ignore the current Pjp because
// it points to a BranchU with no next-left/right JP.

        goto SM2Backtrack;


// ----------------------------------------------------------------------------
// LINEAR LEAF:
//
// Check Decode bytes, if any, in the current JP, then search the leaf for
// *PIndex.

#define    SM1LEAFL(Func)                    \
    Pjll   = P_JLL(Pjp->jp_Addr);            \
    pop1   = JU_JPLEAF_POP0(Pjp) + 1;            \
    offset = Func(Pjll, pop1, *PIndex);        \
    goto SM1LeafLImm

#if (defined(JUDYL) || (! defined(JU_64BIT)))
    case cJU_JPLEAF1:  CHECKDCD(1); SM1LEAFL(j__udySearchLeaf1);
#endif
    case cJU_JPLEAF2:  CHECKDCD(2); SM1LEAFL(j__udySearchLeaf2);
    case cJU_JPLEAF3:  CHECKDCD(3); SM1LEAFL(j__udySearchLeaf3);

#ifdef JU_64BIT
    case cJU_JPLEAF4:  CHECKDCD(4); SM1LEAFL(j__udySearchLeaf4);
    case cJU_JPLEAF5:  CHECKDCD(5); SM1LEAFL(j__udySearchLeaf5);
    case cJU_JPLEAF6:  CHECKDCD(6); SM1LEAFL(j__udySearchLeaf6);
    case cJU_JPLEAF7:  CHECKDCD(7); SM1LEAFL(j__udySearchLeaf7);
#endif

// Common code (state-independent) for all cases of linear leaves and
// immediates:

SM1LeafLImm:
        if (offset >= 0)        // *PIndex is in LeafL / Immed.
#ifdef JUDY1
        JU_RET_FOUND;
#else
        {                // JudyL is trickier...
        switch (JU_JPTYPE(Pjp))
        {
#if (defined(JUDYL) || (! defined(JU_64BIT)))
        case cJU_JPLEAF1: JU_RET_FOUND_LEAF1(Pjll, pop1, offset);
#endif
        case cJU_JPLEAF2: JU_RET_FOUND_LEAF2(Pjll, pop1, offset);
        case cJU_JPLEAF3: JU_RET_FOUND_LEAF3(Pjll, pop1, offset);
#ifdef JU_64BIT
        case cJU_JPLEAF4: JU_RET_FOUND_LEAF4(Pjll, pop1, offset);
        case cJU_JPLEAF5: JU_RET_FOUND_LEAF5(Pjll, pop1, offset);
        case cJU_JPLEAF6: JU_RET_FOUND_LEAF6(Pjll, pop1, offset);
        case cJU_JPLEAF7: JU_RET_FOUND_LEAF7(Pjll, pop1, offset);
#endif

        case cJU_JPIMMED_1_01:
        case cJU_JPIMMED_2_01:
        case cJU_JPIMMED_3_01:
#ifdef JU_64BIT
        case cJU_JPIMMED_4_01:
        case cJU_JPIMMED_5_01:
        case cJU_JPIMMED_6_01:
        case cJU_JPIMMED_7_01:
#endif
            JU_RET_FOUND_IMM_01(Pjp);

        case cJU_JPIMMED_1_02:
        case cJU_JPIMMED_1_03:
#ifdef JU_64BIT
        case cJU_JPIMMED_1_04:
        case cJU_JPIMMED_1_05:
        case cJU_JPIMMED_1_06:
        case cJU_JPIMMED_1_07:
        case cJU_JPIMMED_2_02:
        case cJU_JPIMMED_2_03:
        case cJU_JPIMMED_3_02:
#endif
            JU_RET_FOUND_IMM(Pjp, offset);
        }

        JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);  // impossible?
        JUDY1CODE(return(JERRI );)
        JUDYLCODE(return(PPJERR);)

        } // found *PIndex

#endif // JUDYL

// Dead end, no Index in LeafL / Immed for remaining digit(s) in *PIndex:
//
// Get the ideal location of Index, and if theres no next-left/right Index in
// the LeafL / Immed, shortcut and start backtracking one level up; ignore the
// current Pjp because it points to a LeafL / Immed with no next-left/right
// Index.

#ifdef JUDYPREV
        if ((offset = (~offset) - 1) < 0)    // no next-left Index.
#else
        if ((offset = (~offset)) >= pop1)    // no next-right Index.
#endif
        goto SM2Backtrack;

// Theres a next-left/right Index in the current LeafL / Immed; shortcut by
// copying its digit(s) to *PIndex and returning it.
//
// Unfortunately this is pretty hairy, especially avoiding endian issues.
//
// The cJU_JPLEAF* cases are very similar to same-index-size cJU_JPIMMED* cases
// for *_02 and above, but must return differently, at least for JudyL, so
// spell them out separately here at the cost of a little redundant code for
// Judy1.

        switch (JU_JPTYPE(Pjp))
        {
#if (defined(JUDYL) || (! defined(JU_64BIT)))
        case cJU_JPLEAF1:

        JU_SETDIGIT1(*PIndex, ((uint8_t *) Pjll)[offset]);
        JU_RET_FOUND_LEAF1(Pjll, pop1, offset);
#endif

        case cJU_JPLEAF2:

        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(2)))
            | ((uint16_t *) Pjll)[offset];
        JU_RET_FOUND_LEAF2(Pjll, pop1, offset);

        case cJU_JPLEAF3:
        {
        Word_t lsb;
        JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (3 * offset));
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
        JU_RET_FOUND_LEAF3(Pjll, pop1, offset);
        }

#ifdef JU_64BIT
        case cJU_JPLEAF4:

        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(4)))
            | ((uint32_t *) Pjll)[offset];
        JU_RET_FOUND_LEAF4(Pjll, pop1, offset);

        case cJU_JPLEAF5:
        {
        Word_t lsb;
        JU_COPY5_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (5 * offset));
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(5))) | lsb;
        JU_RET_FOUND_LEAF5(Pjll, pop1, offset);
        }

        case cJU_JPLEAF6:
        {
        Word_t lsb;
        JU_COPY6_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (6 * offset));
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(6))) | lsb;
        JU_RET_FOUND_LEAF6(Pjll, pop1, offset);
        }

        case cJU_JPLEAF7:
        {
        Word_t lsb;
        JU_COPY7_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (7 * offset));
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(7))) | lsb;
        JU_RET_FOUND_LEAF7(Pjll, pop1, offset);
        }

#endif // JU_64BIT

#define    SET_01(cState)  JU_SETDIGITS(*PIndex, JU_JPDCDPOP0(Pjp), cState)

        case cJU_JPIMMED_1_01: SET_01(1); goto SM1Imm_01;
        case cJU_JPIMMED_2_01: SET_01(2); goto SM1Imm_01;
        case cJU_JPIMMED_3_01: SET_01(3); goto SM1Imm_01;
#ifdef JU_64BIT
        case cJU_JPIMMED_4_01: SET_01(4); goto SM1Imm_01;
        case cJU_JPIMMED_5_01: SET_01(5); goto SM1Imm_01;
        case cJU_JPIMMED_6_01: SET_01(6); goto SM1Imm_01;
        case cJU_JPIMMED_7_01: SET_01(7); goto SM1Imm_01;
#endif
SM1Imm_01:    JU_RET_FOUND_IMM_01(Pjp);

// Shorthand for where to find start of Index bytes array:

#ifdef JUDY1
#define    PJI (Pjp->jp_1Index)
#else
#define    PJI (Pjp->jp_LIndex)
#endif

        case cJU_JPIMMED_1_02:
        case cJU_JPIMMED_1_03:
#if (defined(JUDY1) || defined(JU_64BIT))
        case cJU_JPIMMED_1_04:
        case cJU_JPIMMED_1_05:
        case cJU_JPIMMED_1_06:
        case cJU_JPIMMED_1_07:
#endif
#if (defined(JUDY1) && defined(JU_64BIT))
        case cJ1_JPIMMED_1_08:
        case cJ1_JPIMMED_1_09:
        case cJ1_JPIMMED_1_10:
        case cJ1_JPIMMED_1_11:
        case cJ1_JPIMMED_1_12:
        case cJ1_JPIMMED_1_13:
        case cJ1_JPIMMED_1_14:
        case cJ1_JPIMMED_1_15:
#endif
        JU_SETDIGIT1(*PIndex, ((uint8_t *) PJI)[offset]);
        JU_RET_FOUND_IMM(Pjp, offset);

#if (defined(JUDY1) || defined(JU_64BIT))
        case cJU_JPIMMED_2_02:
        case cJU_JPIMMED_2_03:
#endif
#if (defined(JUDY1) && defined(JU_64BIT))
        case cJ1_JPIMMED_2_04:
        case cJ1_JPIMMED_2_05:
        case cJ1_JPIMMED_2_06:
        case cJ1_JPIMMED_2_07:
#endif
#if (defined(JUDY1) || defined(JU_64BIT))
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(2)))
            | ((uint16_t *) PJI)[offset];
        JU_RET_FOUND_IMM(Pjp, offset);
#endif

#if (defined(JUDY1) || defined(JU_64BIT))
        case cJU_JPIMMED_3_02:
#endif
#if (defined(JUDY1) && defined(JU_64BIT))
        case cJ1_JPIMMED_3_03:
        case cJ1_JPIMMED_3_04:
        case cJ1_JPIMMED_3_05:
#endif
#if (defined(JUDY1) || defined(JU_64BIT))
        {
        Word_t lsb;
        JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (3 * offset));
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
        JU_RET_FOUND_IMM(Pjp, offset);
        }
#endif

#if (defined(JUDY1) && defined(JU_64BIT))
        case cJ1_JPIMMED_4_02:
        case cJ1_JPIMMED_4_03:

        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(4)))
            | ((uint32_t *) PJI)[offset];
        JU_RET_FOUND_IMM(Pjp, offset);

        case cJ1_JPIMMED_5_02:
        case cJ1_JPIMMED_5_03:
        {
        Word_t lsb;
        JU_COPY5_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (5 * offset));
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(5))) | lsb;
        JU_RET_FOUND_IMM(Pjp, offset);
        }

        case cJ1_JPIMMED_6_02:
        {
        Word_t lsb;
        JU_COPY6_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (6 * offset));
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(6))) | lsb;
        JU_RET_FOUND_IMM(Pjp, offset);
        }

        case cJ1_JPIMMED_7_02:
        {
        Word_t lsb;
        JU_COPY7_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (7 * offset));
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(7))) | lsb;
        JU_RET_FOUND_IMM(Pjp, offset);
        }

#endif // (JUDY1 && JU_64BIT)

        } // switch for not-found *PIndex

        JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);    // impossible?
        JUDY1CODE(return(JERRI );)
        JUDYLCODE(return(PPJERR);)


// ----------------------------------------------------------------------------
// BITMAP LEAF:
//
// Check Decode bytes, if any, in the current JP, then look in the leaf for
// *PIndex.

    case cJU_JPLEAF_B1:
    {
        Pjlb_t Pjlb;
        CHECKDCD(1);

        Pjlb    = P_JLB(Pjp->jp_Addr);
        digit       = JU_DIGITATSTATE(*PIndex, 1);
        subexp      = JU_SUBEXPL(digit);
        bitposmask  = JU_BITPOSMASKL(digit);
        assert(subexp < cJU_NUMSUBEXPL);    // falls in expected range.

// *PIndex exists in LeafB1:

//        if (JU_BITMAPTESTL(Pjlb, digit))            // slower.
        if (JU_JLB_BITMAP(Pjlb, subexp) & bitposmask)    // faster.
        {
#ifdef JUDYL                // needs offset at this point:
        offset = SEARCHBITMAPL(JU_JLB_BITMAP(Pjlb, subexp), digit, bitposmask);
#endif
        JU_RET_FOUND_LEAF_B1(Pjlb, subexp, offset);
//    == return((PPvoid_t) (P_JV(JL_JLB_PVALUE(Pjlb, subexp)) + (offset)));
        }

// Dead end, no Index in LeafB1 for remaining digit in *PIndex:
//
// If theres a next-left/right Index in the current LeafB1, which for
// Judy*Next() is true if any bits are set for higher Indexes, shortcut by
// returning it.  Note:  For Judy*Prev(), offset is set here to the correct
// value for the next-left JP.

        offset = SEARCHBITMAPL(JU_JLB_BITMAP(Pjlb, subexp), digit,
                   bitposmask);
        // right range:
        assert((offset >= -1) && (offset < (int) cJU_BITSPERSUBEXPL));

#ifdef JUDYPREV
        if (offset >= 0)        // next-left JP is in this subexpanse.
        goto SM1LeafB1Findlimit;

        while (--subexp >= 0)        // search next-left subexpanses.
#else
        if (JU_JLB_BITMAP(Pjlb, subexp) & JU_MASKHIGHEREXC(bitposmask))
        {
        ++offset;            // next-left => next-right.
        goto SM1LeafB1Findlimit;
        }

        while (++subexp < cJU_NUMSUBEXPL)    // search next-right subexps.
#endif
        {
        if (! JU_JLB_BITMAP(Pjlb, subexp)) continue;  // empty subexp.

#ifdef JUDYPREV
        offset = SEARCHBITMAPMAXL(JU_JLB_BITMAP(Pjlb, subexp));
        // expected range:
        assert((offset >= 0) && (offset < (int) cJU_BITSPERSUBEXPL));
#else
        offset = 0;
#endif

// Save the next-left/right Indexess digit in *PIndex:

SM1LeafB1Findlimit:
        JU_BITMAPDIGITL(digit, subexp, JU_JLB_BITMAP(Pjlb, subexp), offset);
        JU_SETDIGIT1(*PIndex, digit);
        JU_RET_FOUND_LEAF_B1(Pjlb, subexp, offset);
//    == return((PPvoid_t) (P_JV(JL_JLB_PVALUE(Pjlb, subexp)) + (offset)));
        }

// Theres no next-left/right Index in the LeafB1:
//
// Shortcut and start backtracking one level up; ignore the current Pjp because
// it points to a LeafB1 with no next-left/right Index.

        goto SM2Backtrack;

    } // case cJU_JPLEAF_B1

#ifdef JUDY1
// ----------------------------------------------------------------------------
// FULL POPULATION:
//
// If the Decode bytes match, *PIndex is found (without modification).

    case cJ1_JPFULLPOPU1:

        CHECKDCD(1);
        JU_RET_FOUND_FULLPOPU1;
#endif


// ----------------------------------------------------------------------------
// IMMEDIATE:

#ifdef JUDYPREV
#define    SM1IMM_SETPOP1(cPop1)
#else
#define SM1IMM_SETPOP1(cPop1)  pop1 = (cPop1)
#endif

#define    SM1IMM(Func,cPop1)                \
    SM1IMM_SETPOP1(cPop1);                \
    offset = Func((Pjll_t) (PJI), cPop1, *PIndex);    \
    goto SM1LeafLImm

// Special case for Pop1 = 1 Immediate JPs:
//
// If *PIndex is in the immediate, offset is 0, otherwise the binary NOT of the
// offset where it belongs, 0 or 1, same as from the search functions.

#ifdef JUDYPREV
#define    SM1IMM_01_SETPOP1
#else
#define SM1IMM_01_SETPOP1  pop1 = 1
#endif

#define    SM1IMM_01                              \
    SM1IMM_01_SETPOP1;                          \
    offset = ((JU_JPDCDPOP0(Pjp) <  JU_TRIMTODCDSIZE(*PIndex)) ? ~1 : \
          (JU_JPDCDPOP0(Pjp) == JU_TRIMTODCDSIZE(*PIndex)) ?  0 : \
                                     ~0); \
    goto SM1LeafLImm

    case cJU_JPIMMED_1_01:
    case cJU_JPIMMED_2_01:
    case cJU_JPIMMED_3_01:
#ifdef JU_64BIT
    case cJU_JPIMMED_4_01:
    case cJU_JPIMMED_5_01:
    case cJU_JPIMMED_6_01:
    case cJU_JPIMMED_7_01:
#endif
        SM1IMM_01;

// TBD:  Doug says it would be OK to have fewer calls and calculate arg 2, here
// and in Judy*Count() also.

    case cJU_JPIMMED_1_02:  SM1IMM(j__udySearchLeaf1,  2);
    case cJU_JPIMMED_1_03:  SM1IMM(j__udySearchLeaf1,  3);
#if (defined(JUDY1) || defined(JU_64BIT))
    case cJU_JPIMMED_1_04:  SM1IMM(j__udySearchLeaf1,  4);
    case cJU_JPIMMED_1_05:  SM1IMM(j__udySearchLeaf1,  5);
    case cJU_JPIMMED_1_06:  SM1IMM(j__udySearchLeaf1,  6);
    case cJU_JPIMMED_1_07:  SM1IMM(j__udySearchLeaf1,  7);
#endif
#if (defined(JUDY1) && defined(JU_64BIT))
    case cJ1_JPIMMED_1_08:  SM1IMM(j__udySearchLeaf1,  8);
    case cJ1_JPIMMED_1_09:  SM1IMM(j__udySearchLeaf1,  9);
    case cJ1_JPIMMED_1_10:  SM1IMM(j__udySearchLeaf1, 10);
    case cJ1_JPIMMED_1_11:  SM1IMM(j__udySearchLeaf1, 11);
    case cJ1_JPIMMED_1_12:  SM1IMM(j__udySearchLeaf1, 12);
    case cJ1_JPIMMED_1_13:  SM1IMM(j__udySearchLeaf1, 13);
    case cJ1_JPIMMED_1_14:  SM1IMM(j__udySearchLeaf1, 14);
    case cJ1_JPIMMED_1_15:  SM1IMM(j__udySearchLeaf1, 15);
#endif

#if (defined(JUDY1) || defined(JU_64BIT))
    case cJU_JPIMMED_2_02:  SM1IMM(j__udySearchLeaf2,  2);
    case cJU_JPIMMED_2_03:  SM1IMM(j__udySearchLeaf2,  3);
#endif
#if (defined(JUDY1) && defined(JU_64BIT))
    case cJ1_JPIMMED_2_04:  SM1IMM(j__udySearchLeaf2,  4);
    case cJ1_JPIMMED_2_05:  SM1IMM(j__udySearchLeaf2,  5);
    case cJ1_JPIMMED_2_06:  SM1IMM(j__udySearchLeaf2,  6);
    case cJ1_JPIMMED_2_07:  SM1IMM(j__udySearchLeaf2,  7);
#endif

#if (defined(JUDY1) || defined(JU_64BIT))
    case cJU_JPIMMED_3_02:  SM1IMM(j__udySearchLeaf3,  2);
#endif
#if (defined(JUDY1) && defined(JU_64BIT))
    case cJ1_JPIMMED_3_03:  SM1IMM(j__udySearchLeaf3,  3);
    case cJ1_JPIMMED_3_04:  SM1IMM(j__udySearchLeaf3,  4);
    case cJ1_JPIMMED_3_05:  SM1IMM(j__udySearchLeaf3,  5);

    case cJ1_JPIMMED_4_02:  SM1IMM(j__udySearchLeaf4,  2);
    case cJ1_JPIMMED_4_03:  SM1IMM(j__udySearchLeaf4,  3);

    case cJ1_JPIMMED_5_02:  SM1IMM(j__udySearchLeaf5,  2);
    case cJ1_JPIMMED_5_03:  SM1IMM(j__udySearchLeaf5,  3);

    case cJ1_JPIMMED_6_02:  SM1IMM(j__udySearchLeaf6,  2);

    case cJ1_JPIMMED_7_02:  SM1IMM(j__udySearchLeaf7,  2);
#endif


// ----------------------------------------------------------------------------
// INVALID JP TYPE:

    default: JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
         JUDY1CODE(return(JERRI );)
         JUDYLCODE(return(PPJERR);)

    } // SM1Get switch.

    /*NOTREACHED*/


// ============================================================================
// STATE MACHINE 2 -- BACKTRACK BRANCH TO PREVIOUS JP:
//
// Look for the next-left/right JP in a branch, backing up the history list as
// necessary.  Upon finding a next-left/right JP, modify the corresponding
// digit in *PIndex before passing control to SM3Findlimit.
//
// Note:  As described earlier, only branch JPs are expected here; other types
// fall into the default case.
//
// Note:  If a found JP contains needed Dcd bytes, thats OK, theyre copied to
// *PIndex in SM3Findlimit.
//
// TBD:  This code has a lot in common with similar code in the shortcut cases
// in SM1Get.  Can combine this code somehow?
//
// ENTRY:  List, possibly empty, of JPs and offsets in APjphist[] and
// Aoffhist[]; see earlier comments.
//
// EXIT:  Execute JU_RET_NOTFOUND if no previous/next JP; otherwise jump to
// SM3Findlimit to resume a new but different downward search.

SM2Backtrack:        // come or return here for first/next sideways search.

    HISTPOP(Pjp, offset);

    switch (JU_JPTYPE(Pjp))
    {


// ----------------------------------------------------------------------------
// LINEAR BRANCH:

    case cJU_JPBRANCH_L2: state = 2;         goto SM2BranchL;
    case cJU_JPBRANCH_L3: state = 3;         goto SM2BranchL;
#ifdef JU_64BIT
    case cJU_JPBRANCH_L4: state = 4;         goto SM2BranchL;
    case cJU_JPBRANCH_L5: state = 5;         goto SM2BranchL;
    case cJU_JPBRANCH_L6: state = 6;         goto SM2BranchL;
    case cJU_JPBRANCH_L7: state = 7;         goto SM2BranchL;
#endif
    case cJU_JPBRANCH_L:  state = cJU_ROOTSTATE; goto SM2BranchL;

SM2BranchL:
#ifdef JUDYPREV
        if (--offset < 0) goto SM2Backtrack;  // no next-left JP in BranchL.
#endif
        Pjbl = P_JBL(Pjp->jp_Addr);
#ifdef JUDYNEXT
        if (++offset >= (Pjbl->jbl_NumJPs)) goto SM2Backtrack;
                        // no next-right JP in BranchL.
#endif

// Theres a next-left/right JP in the current BranchL; save its digit in
// *PIndex and continue with SM3Findlimit:

        JU_SETDIGIT(*PIndex, Pjbl->jbl_Expanse[offset], state);
        Pjp = (Pjbl->jbl_jp) + offset;
        goto SM3Findlimit;


// ----------------------------------------------------------------------------
// BITMAP BRANCH:

    case cJU_JPBRANCH_B2: state = 2;         goto SM2BranchB;
    case cJU_JPBRANCH_B3: state = 3;         goto SM2BranchB;
#ifdef JU_64BIT
    case cJU_JPBRANCH_B4: state = 4;         goto SM2BranchB;
    case cJU_JPBRANCH_B5: state = 5;         goto SM2BranchB;
    case cJU_JPBRANCH_B6: state = 6;         goto SM2BranchB;
    case cJU_JPBRANCH_B7: state = 7;         goto SM2BranchB;
#endif
    case cJU_JPBRANCH_B:  state = cJU_ROOTSTATE; goto SM2BranchB;

SM2BranchB:
        Pjbb = P_JBB(Pjp->jp_Addr);
        HISTPOPBOFF(subexp, offset, digit);        // unpack values.

// If theres a next-left/right JP in the current BranchB, which for
// Judy*Next() is true if any bits are set for higher Indexes, continue to
// SM3Findlimit:
//
// Note:  offset is set to the JP previously traversed; go one to the
// left/right.

#ifdef JUDYPREV
        if (offset > 0)        // next-left JP is in this subexpanse.
        {
        --offset;
        goto SM2BranchBFindlimit;
        }

        while (--subexp >= 0)        // search next-left subexpanses.
#else
        if (JU_JBB_BITMAP(Pjbb, subexp)
          & JU_MASKHIGHEREXC(JU_BITPOSMASKB(digit)))
        {
        ++offset;            // next-left => next-right.
        goto SM2BranchBFindlimit;
        }

        while (++subexp < cJU_NUMSUBEXPB)    // search next-right subexps.
#endif
        {
        if (! JU_JBB_PJP(Pjbb, subexp)) continue;  // empty subexpanse.

#ifdef JUDYPREV
        offset = SEARCHBITMAPMAXB(JU_JBB_BITMAP(Pjbb, subexp));
        // expected range:
        assert((offset >= 0) && (offset < cJU_BITSPERSUBEXPB));
#else
        offset = 0;
#endif

// Save the next-left/right JPs digit in *PIndex:

SM2BranchBFindlimit:
        JU_BITMAPDIGITB(digit, subexp, JU_JBB_BITMAP(Pjbb, subexp),
                offset);
        JU_SETDIGIT(*PIndex, digit, state);

        if ((Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp))) == (Pjp_t) NULL)
        {
            JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
            JUDY1CODE(return(JERRI );)
            JUDYLCODE(return(PPJERR);)
        }

        Pjp += offset;
        goto SM3Findlimit;
        }

// Theres no next-left/right JP in the BranchB:

        goto SM2Backtrack;


// ----------------------------------------------------------------------------
// UNCOMPRESSED BRANCH:

    case cJU_JPBRANCH_U2: state = 2;         goto SM2BranchU;
    case cJU_JPBRANCH_U3: state = 3;         goto SM2BranchU;
#ifdef JU_64BIT
    case cJU_JPBRANCH_U4: state = 4;         goto SM2BranchU;
    case cJU_JPBRANCH_U5: state = 5;         goto SM2BranchU;
    case cJU_JPBRANCH_U6: state = 6;         goto SM2BranchU;
    case cJU_JPBRANCH_U7: state = 7;         goto SM2BranchU;
#endif
    case cJU_JPBRANCH_U:  state = cJU_ROOTSTATE; goto SM2BranchU;

SM2BranchU:

// Search for a next-left/right JP in the current BranchU, and if one is found,
// save its digit in *PIndex and continue to SM3Findlimit:

        Pjbu  = P_JBU(Pjp->jp_Addr);
        digit = offset;

#ifdef JUDYPREV
        while (digit >= 1)
        {
        Pjp = (Pjbu->jbu_jp) + (--digit);
#else
        while (digit < cJU_BRANCHUNUMJPS - 1)
        {
        Pjp = (Pjbu->jbu_jp) + (++digit);
#endif
        if (JPNULL(JU_JPTYPE(Pjp))) continue;

        JU_SETDIGIT(*PIndex, digit, state);
        goto SM3Findlimit;
        }

// Theres no next-left/right JP in the BranchU:

        goto SM2Backtrack;


// ----------------------------------------------------------------------------
// INVALID JP TYPE:

    default: JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
         JUDY1CODE(return(JERRI );)
         JUDYLCODE(return(PPJERR);)

    } // SM2Backtrack switch.

    /*NOTREACHED*/


// ============================================================================
// STATE MACHINE 3 -- FIND LIMIT JP/INDEX:
//
// Look for the highest/lowest (right/left-most) JP in each branch and the
// highest/lowest Index in a leaf or immediate, and return it.  While
// traversing, modify appropriate digit(s) in *PIndex to reflect the path
// taken, including Dcd bytes in each JP (which could hold critical missing
// digits for skipped branches).
//
// ENTRY:  Pjp set to a JP under which to find max/min JPs (if a branch JP) or
// a max/min Index and return (if a leaf or immediate JP).
//
// EXIT:  Execute JU_RET_FOUND* upon reaching a leaf or immediate.  Should be
// impossible to fail, unless the Judy array is corrupt.

SM3Findlimit:        // come or return here for first/next branch/leaf.

    switch (JU_JPTYPE(Pjp))
    {
// ----------------------------------------------------------------------------
// LINEAR BRANCH:
//
// Simply use the highest/lowest (right/left-most) JP in the BranchL, but first
// copy the Dcd bytes to *PIndex if there are any (only if state <
// cJU_ROOTSTATE - 1).

    case cJU_JPBRANCH_L2:  SM3PREPB_DCD(2, SM3BranchL);
#ifndef JU_64BIT
    case cJU_JPBRANCH_L3:  SM3PREPB(    3, SM3BranchL);
#else
    case cJU_JPBRANCH_L3:  SM3PREPB_DCD(3, SM3BranchL);
    case cJU_JPBRANCH_L4:  SM3PREPB_DCD(4, SM3BranchL);
    case cJU_JPBRANCH_L5:  SM3PREPB_DCD(5, SM3BranchL);
    case cJU_JPBRANCH_L6:  SM3PREPB_DCD(6, SM3BranchL);
    case cJU_JPBRANCH_L7:  SM3PREPB(    7, SM3BranchL);
#endif
    case cJU_JPBRANCH_L:   SM3PREPB(    cJU_ROOTSTATE, SM3BranchL);

SM3BranchL:
        Pjbl = P_JBL(Pjp->jp_Addr);

#ifdef JUDYPREV
        if ((offset = (Pjbl->jbl_NumJPs) - 1) < 0)
#else
        offset = 0; if ((Pjbl->jbl_NumJPs) == 0)
#endif
        {
        JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
        JUDY1CODE(return(JERRI );)
        JUDYLCODE(return(PPJERR);)
        }

        JU_SETDIGIT(*PIndex, Pjbl->jbl_Expanse[offset], state);
        Pjp = (Pjbl->jbl_jp) + offset;
        goto SM3Findlimit;


// ----------------------------------------------------------------------------
// BITMAP BRANCH:
//
// Look for the highest/lowest (right/left-most) non-null subexpanse, then use
// the highest/lowest JP in that subexpanse, but first copy Dcd bytes, if there
// are any (only if state < cJU_ROOTSTATE - 1), to *PIndex.

    case cJU_JPBRANCH_B2:  SM3PREPB_DCD(2, SM3BranchB);
#ifndef JU_64BIT
    case cJU_JPBRANCH_B3:  SM3PREPB(    3, SM3BranchB);
#else
    case cJU_JPBRANCH_B3:  SM3PREPB_DCD(3, SM3BranchB);
    case cJU_JPBRANCH_B4:  SM3PREPB_DCD(4, SM3BranchB);
    case cJU_JPBRANCH_B5:  SM3PREPB_DCD(5, SM3BranchB);
    case cJU_JPBRANCH_B6:  SM3PREPB_DCD(6, SM3BranchB);
    case cJU_JPBRANCH_B7:  SM3PREPB(    7, SM3BranchB);
#endif
    case cJU_JPBRANCH_B:   SM3PREPB(    cJU_ROOTSTATE, SM3BranchB);

SM3BranchB:
        Pjbb   = P_JBB(Pjp->jp_Addr);
#ifdef JUDYPREV
        subexp = cJU_NUMSUBEXPB;

        while (! (JU_JBB_BITMAP(Pjbb, --subexp)))  // find non-empty subexp.
        {
        if (subexp <= 0)            // wholly empty bitmap.
        {
            JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
            JUDY1CODE(return(JERRI );)
            JUDYLCODE(return(PPJERR);)
        }
        }

        offset = SEARCHBITMAPMAXB(JU_JBB_BITMAP(Pjbb, subexp));
        // expected range:
        assert((offset >= 0) && (offset < cJU_BITSPERSUBEXPB));
#else
        subexp = -1;

        while (! (JU_JBB_BITMAP(Pjbb, ++subexp)))  // find non-empty subexp.
        {
        if (subexp >= cJU_NUMSUBEXPB - 1)      // didnt find one.
        {
            JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
            JUDY1CODE(return(JERRI );)
            JUDYLCODE(return(PPJERR);)
        }
        }

        offset = 0;
#endif

        JU_BITMAPDIGITB(digit, subexp, JU_JBB_BITMAP(Pjbb, subexp), offset);
        JU_SETDIGIT(*PIndex, digit, state);

        if ((Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp))) == (Pjp_t) NULL)
        {
        JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
        JUDY1CODE(return(JERRI );)
        JUDYLCODE(return(PPJERR);)
        }

        Pjp += offset;
        goto SM3Findlimit;


// ----------------------------------------------------------------------------
// UNCOMPRESSED BRANCH:
//
// Look for the highest/lowest (right/left-most) non-null JP, and use it, but
// first copy Dcd bytes to *PIndex if there are any (only if state <
// cJU_ROOTSTATE - 1).

    case cJU_JPBRANCH_U2:  SM3PREPB_DCD(2, SM3BranchU);
#ifndef JU_64BIT
    case cJU_JPBRANCH_U3:  SM3PREPB(    3, SM3BranchU);
#else
    case cJU_JPBRANCH_U3:  SM3PREPB_DCD(3, SM3BranchU);
    case cJU_JPBRANCH_U4:  SM3PREPB_DCD(4, SM3BranchU);
    case cJU_JPBRANCH_U5:  SM3PREPB_DCD(5, SM3BranchU);
    case cJU_JPBRANCH_U6:  SM3PREPB_DCD(6, SM3BranchU);
    case cJU_JPBRANCH_U7:  SM3PREPB(    7, SM3BranchU);
#endif
    case cJU_JPBRANCH_U:   SM3PREPB(    cJU_ROOTSTATE, SM3BranchU);

SM3BranchU:
        Pjbu  = P_JBU(Pjp->jp_Addr);
#ifdef JUDYPREV
        digit = cJU_BRANCHUNUMJPS;

        while (digit >= 1)
        {
        Pjp = (Pjbu->jbu_jp) + (--digit);
#else

        for (digit = 0; digit < cJU_BRANCHUNUMJPS; ++digit)
        {
        Pjp = (Pjbu->jbu_jp) + digit;
#endif
        if (JPNULL(JU_JPTYPE(Pjp))) continue;

        JU_SETDIGIT(*PIndex, digit, state);
        goto SM3Findlimit;
        }

// No non-null JPs in BranchU:

        JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
        JUDY1CODE(return(JERRI );)
        JUDYLCODE(return(PPJERR);)


// ----------------------------------------------------------------------------
// LINEAR LEAF:
//
// Simply use the highest/lowest (right/left-most) Index in the LeafL, but the
// details vary depending on leaf Index Size.  First copy Dcd bytes, if there
// are any (only if state < cJU_ROOTSTATE - 1), to *PIndex.

#define    SM3LEAFLDCD(cState)                \
    JU_SETDCD(*PIndex, Pjp, cState);            \
    SM3LEAFLNODCD

#ifdef JUDY1
#define    SM3LEAFL_SETPOP1        // not needed in any cases.
#else
#define    SM3LEAFL_SETPOP1  pop1 = JU_JPLEAF_POP0(Pjp) + 1
#endif

#ifdef JUDYPREV
#define    SM3LEAFLNODCD            \
    Pjll = P_JLL(Pjp->jp_Addr);    \
    SM3LEAFL_SETPOP1;        \
    offset = JU_JPLEAF_POP0(Pjp); assert(offset >= 0)
#else
#define    SM3LEAFLNODCD            \
    Pjll = P_JLL(Pjp->jp_Addr);    \
    SM3LEAFL_SETPOP1;        \
    offset = 0; assert(JU_JPLEAF_POP0(Pjp) >= 0);
#endif

#if (defined(JUDYL) || (! defined(JU_64BIT)))
    case cJU_JPLEAF1:

        SM3LEAFLDCD(1);
        JU_SETDIGIT1(*PIndex, ((uint8_t *) Pjll)[offset]);
        JU_RET_FOUND_LEAF1(Pjll, pop1, offset);
#endif

    case cJU_JPLEAF2:

        SM3LEAFLDCD(2);
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(2)))
            | ((uint16_t *) Pjll)[offset];
        JU_RET_FOUND_LEAF2(Pjll, pop1, offset);

#ifndef JU_64BIT
    case cJU_JPLEAF3:
    {
        Word_t lsb;
        SM3LEAFLNODCD;
        JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (3 * offset));
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
        JU_RET_FOUND_LEAF3(Pjll, pop1, offset);
    }

#else
    case cJU_JPLEAF3:
    {
        Word_t lsb;
        SM3LEAFLDCD(3);
        JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (3 * offset));
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
        JU_RET_FOUND_LEAF3(Pjll, pop1, offset);
    }

    case cJU_JPLEAF4:

        SM3LEAFLDCD(4);
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(4)))
            | ((uint32_t *) Pjll)[offset];
        JU_RET_FOUND_LEAF4(Pjll, pop1, offset);

    case cJU_JPLEAF5:
    {
        Word_t lsb;
        SM3LEAFLDCD(5);
        JU_COPY5_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (5 * offset));
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(5))) | lsb;
        JU_RET_FOUND_LEAF5(Pjll, pop1, offset);
    }

    case cJU_JPLEAF6:
    {
        Word_t lsb;
        SM3LEAFLDCD(6);
        JU_COPY6_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (6 * offset));
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(6))) | lsb;
        JU_RET_FOUND_LEAF6(Pjll, pop1, offset);
    }

    case cJU_JPLEAF7:
    {
        Word_t lsb;
        SM3LEAFLNODCD;
        JU_COPY7_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (7 * offset));
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(7))) | lsb;
        JU_RET_FOUND_LEAF7(Pjll, pop1, offset);
    }
#endif


// ----------------------------------------------------------------------------
// BITMAP LEAF:
//
// Look for the highest/lowest (right/left-most) non-null subexpanse, then use
// the highest/lowest Index in that subexpanse, but first copy Dcd bytes
// (always present since state 1 < cJU_ROOTSTATE) to *PIndex.

    case cJU_JPLEAF_B1:
    {
        Pjlb_t Pjlb;

        JU_SETDCD(*PIndex, Pjp, 1);

        Pjlb   = P_JLB(Pjp->jp_Addr);
#ifdef JUDYPREV
        subexp = cJU_NUMSUBEXPL;

        while (! JU_JLB_BITMAP(Pjlb, --subexp))  // find non-empty subexp.
        {
        if (subexp <= 0)        // wholly empty bitmap.
        {
            JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
            JUDY1CODE(return(JERRI );)
            JUDYLCODE(return(PPJERR);)
        }
        }

// TBD:  Might it be faster to just use a variant of BITMAPDIGIT*() that yields
// the digit for the right-most Index with a bit set?

        offset = SEARCHBITMAPMAXL(JU_JLB_BITMAP(Pjlb, subexp));
        // expected range:
        assert((offset >= 0) && (offset < cJU_BITSPERSUBEXPL));
#else
        subexp = -1;

        while (! JU_JLB_BITMAP(Pjlb, ++subexp))  // find non-empty subexp.
        {
        if (subexp >= cJU_NUMSUBEXPL - 1)    // didnt find one.
        {
            JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
            JUDY1CODE(return(JERRI );)
            JUDYLCODE(return(PPJERR);)
        }
        }

        offset = 0;
#endif

        JU_BITMAPDIGITL(digit, subexp, JU_JLB_BITMAP(Pjlb, subexp), offset);
        JU_SETDIGIT1(*PIndex, digit);
        JU_RET_FOUND_LEAF_B1(Pjlb, subexp, offset);
//    == return((PPvoid_t) (P_JV(JL_JLB_PVALUE(Pjlb, subexp)) + (offset)));

    } // case cJU_JPLEAF_B1

#ifdef JUDY1
// ----------------------------------------------------------------------------
// FULL POPULATION:
//
// Copy Dcd bytes to *PIndex (always present since state 1 < cJU_ROOTSTATE),
// then set the highest/lowest possible digit as the LSB in *PIndex.

    case cJ1_JPFULLPOPU1:

        JU_SETDCD(   *PIndex, Pjp, 1);
#ifdef JUDYPREV
        JU_SETDIGIT1(*PIndex, cJU_BITSPERBITMAP - 1);
#else
        JU_SETDIGIT1(*PIndex, 0);
#endif
        JU_RET_FOUND_FULLPOPU1;
#endif // JUDY1


// ----------------------------------------------------------------------------
// IMMEDIATE:
//
// Simply use the highest/lowest (right/left-most) Index in the Imm, but the
// details vary depending on leaf Index Size and pop1.  Note:  There are no Dcd
// bytes in an Immediate JP, but in a cJU_JPIMMED_*_01 JP, the field holds the
// least bytes of the immediate Index.

    case cJU_JPIMMED_1_01: SET_01(1); goto SM3Imm_01;
    case cJU_JPIMMED_2_01: SET_01(2); goto SM3Imm_01;
    case cJU_JPIMMED_3_01: SET_01(3); goto SM3Imm_01;
#ifdef JU_64BIT
    case cJU_JPIMMED_4_01: SET_01(4); goto SM3Imm_01;
    case cJU_JPIMMED_5_01: SET_01(5); goto SM3Imm_01;
    case cJU_JPIMMED_6_01: SET_01(6); goto SM3Imm_01;
    case cJU_JPIMMED_7_01: SET_01(7); goto SM3Imm_01;
#endif
SM3Imm_01:    JU_RET_FOUND_IMM_01(Pjp);

#ifdef JUDYPREV
#define    SM3IMM_OFFSET(cPop1)  (cPop1) - 1    // highest.
#else
#define    SM3IMM_OFFSET(cPop1)  0            // lowest.
#endif

#define    SM3IMM(cPop1,Next)        \
    offset = SM3IMM_OFFSET(cPop1);    \
    goto Next

    case cJU_JPIMMED_1_02: SM3IMM( 2, SM3Imm1);
    case cJU_JPIMMED_1_03: SM3IMM( 3, SM3Imm1);
#if (defined(JUDY1) || defined(JU_64BIT))
    case cJU_JPIMMED_1_04: SM3IMM( 4, SM3Imm1);
    case cJU_JPIMMED_1_05: SM3IMM( 5, SM3Imm1);
    case cJU_JPIMMED_1_06: SM3IMM( 6, SM3Imm1);
    case cJU_JPIMMED_1_07: SM3IMM( 7, SM3Imm1);
#endif
#if (defined(JUDY1) && defined(JU_64BIT))
    case cJ1_JPIMMED_1_08: SM3IMM( 8, SM3Imm1);
    case cJ1_JPIMMED_1_09: SM3IMM( 9, SM3Imm1);
    case cJ1_JPIMMED_1_10: SM3IMM(10, SM3Imm1);
    case cJ1_JPIMMED_1_11: SM3IMM(11, SM3Imm1);
    case cJ1_JPIMMED_1_12: SM3IMM(12, SM3Imm1);
    case cJ1_JPIMMED_1_13: SM3IMM(13, SM3Imm1);
    case cJ1_JPIMMED_1_14: SM3IMM(14, SM3Imm1);
    case cJ1_JPIMMED_1_15: SM3IMM(15, SM3Imm1);
#endif

SM3Imm1:    JU_SETDIGIT1(*PIndex, ((uint8_t *) PJI)[offset]);
        JU_RET_FOUND_IMM(Pjp, offset);

#if (defined(JUDY1) || defined(JU_64BIT))
    case cJU_JPIMMED_2_02: SM3IMM(2, SM3Imm2);
    case cJU_JPIMMED_2_03: SM3IMM(3, SM3Imm2);
#endif
#if (defined(JUDY1) && defined(JU_64BIT))
    case cJ1_JPIMMED_2_04: SM3IMM(4, SM3Imm2);
    case cJ1_JPIMMED_2_05: SM3IMM(5, SM3Imm2);
    case cJ1_JPIMMED_2_06: SM3IMM(6, SM3Imm2);
    case cJ1_JPIMMED_2_07: SM3IMM(7, SM3Imm2);
#endif

#if (defined(JUDY1) || defined(JU_64BIT))
SM3Imm2:    *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(2)))
            | ((uint16_t *) PJI)[offset];
        JU_RET_FOUND_IMM(Pjp, offset);
#endif

#if (defined(JUDY1) || defined(JU_64BIT))
    case cJU_JPIMMED_3_02: SM3IMM(2, SM3Imm3);
#endif
#if (defined(JUDY1) && defined(JU_64BIT))
    case cJ1_JPIMMED_3_03: SM3IMM(3, SM3Imm3);
    case cJ1_JPIMMED_3_04: SM3IMM(4, SM3Imm3);
    case cJ1_JPIMMED_3_05: SM3IMM(5, SM3Imm3);
#endif

#if (defined(JUDY1) || defined(JU_64BIT))
SM3Imm3:
    {
        Word_t lsb;
        JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (3 * offset));
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
        JU_RET_FOUND_IMM(Pjp, offset);
    }
#endif

#if (defined(JUDY1) && defined(JU_64BIT))
    case cJ1_JPIMMED_4_02: SM3IMM(2, SM3Imm4);
    case cJ1_JPIMMED_4_03: SM3IMM(3, SM3Imm4);

SM3Imm4:    *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(4)))
            | ((uint32_t *) PJI)[offset];
        JU_RET_FOUND_IMM(Pjp, offset);

    case cJ1_JPIMMED_5_02: SM3IMM(2, SM3Imm5);
    case cJ1_JPIMMED_5_03: SM3IMM(3, SM3Imm5);

SM3Imm5:
    {
        Word_t lsb;
        JU_COPY5_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (5 * offset));
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(5))) | lsb;
        JU_RET_FOUND_IMM(Pjp, offset);
    }

    case cJ1_JPIMMED_6_02: SM3IMM(2, SM3Imm6);

SM3Imm6:
    {
        Word_t lsb;
        JU_COPY6_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (6 * offset));
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(6))) | lsb;
        JU_RET_FOUND_IMM(Pjp, offset);
    }

    case cJ1_JPIMMED_7_02: SM3IMM(2, SM3Imm7);

SM3Imm7:
    {
        Word_t lsb;
        JU_COPY7_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (7 * offset));
        *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(7))) | lsb;
        JU_RET_FOUND_IMM(Pjp, offset);
    }
#endif // (JUDY1 && JU_64BIT)


// ----------------------------------------------------------------------------
// OTHER CASES:

    default: JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
         JUDY1CODE(return(JERRI );)
         JUDYLCODE(return(PPJERR);)

    } // SM3Findlimit switch.

    /*NOTREACHED*/

} // Judy1Prev() / Judy1Next() / JudyLPrev() / JudyLNext()