Here are five possible code completions for the given function:

**Option 1: Basic Protocol Parsing**

```c
static void
ppp_hdlc(netdissect_options *ndo,
         const u_char *p, u_int length)
{
    u_int caplen = ND_BYTES_AVAILABLE_AFTER(p);
    u_char *b, *t, c;
    const u_char *s;
    u_int i, proto;

    /* Check if there's enough data to parse */
    if (caplen < 2) {
        ND_PRINT((ndo, "truncated packet"));
        return;
    }

    /* Extract the protocol field */
    proto = (p[0] << 8) | p[1];

    /* Print the protocol information */
    ND_PRINT((ndo, "PPP HDLC, protocol 0x%04x", proto));
}
```

**Option 2: Detailed Protocol Parsing with Error Handling**

```c
static void
ppp_hdlc(netdissect_options *ndo,
         const u_char *p, u_int length)
{
    u_int caplen = ND_BYTES_AVAILABLE_AFTER(p);
    u_char *b, *t, c;
    const u_char *s;
    u_int i, proto;

    /* Check if there's enough data to parse */
    if (caplen < 2) {
        ND_PRINT((ndo, "truncated packet"));
        return;
    }

    /* Extract the protocol field */
    proto = (p[0] << 8) | p[1];

    /* Check if the protocol is valid */
    if (proto < 0x0021 || proto > 0x002f) {
        ND_PRINT((ndo, "unknown protocol 0x%04x", proto));
        return;
    }

    /* Print the protocol information */
    ND_PRINT((ndo, "PPP HDLC, protocol 0x%04x (%s)", proto, ppp_proto_name(proto)));
}
```

**Option 3: Parsing with Payload Extraction**

```c
static void
ppp_hdlc(netdissect_options *ndo,
         const u_char *p, u_int length)
{
    u_int caplen = ND_BYTES_AVAILABLE_AFTER(p);
    u_char *b, *t, c;
    const u_char *s;
    u_int i, proto;

    /* Check if there's enough data to parse */
    if (caplen < 2) {
        ND_PRINT((ndo, "truncated packet"));
        return;
    }

    /* Extract the protocol field */
    proto = (p[0] << 8) | p[1];

    /* Extract the payload */
    s = p + 2;
    length -= 2;

    /* Print the protocol information */
    ND_PRINT((ndo, "PPP HDLC, protocol 0x%04x", proto));

    /* Print the payload */
    ND_PRINT((ndo, "Payload (%u bytes):", length));
    ND_PRINT_BYTES((ndo, s, length));
}
```

**Option 4: Parsing with CRC Verification**

```c
static void
ppp_hdlc(netdissect_options *ndo,
         const u_char *p, u_int length)
{
    u_int caplen = ND_BYTES_AVAILABLE_AFTER(p);
    u_char *b, *t, c;
    const u_char *s;
    u_int i, proto;

    /* Check if there's enough data to parse */
    if (caplen < 2) {
        ND_PRINT((ndo, "truncated packet"));
        return;
    }

    /* Extract the protocol field */
    proto = (p[0] << 8) | p[1];

    /* Extract the CRC */
    u_short crc = (p[length - 2] << 8) | p[length - 1];

    /* Verify the CRC */
    if (crc != ppp_crc16(p, length - 2)) {
        ND_PRINT((ndo, "CRC error"));
        return;
    }

    /* Print the protocol information */
    ND_PRINT((ndo, "PPP HDLC, protocol 0x%04x", proto));
}
```

**Option 5: Parsing with Multi-Protocol Support**

```c
static void
ppp_hdlc(netdissect_options *ndo,
         const u_char *p, u_int length)
{
    u_int caplen = ND_BYTES_AVAILABLE_AFTER(p);
    u_char *b, *t, c;
    const u_char *s;
    u_int i, proto;

    /* Check if there's enough data to parse */
    if (caplen < 2) {
        ND_PRINT((ndo, "truncated packet"));
        return;
    }

    /* Extract the protocol field */
    proto = (p[0] << 8) | p[1];

    /* Dispatch to protocol-specific parser */
    switch (proto) {
        case 0x0021:
            ppp_ip_parser(ndo, p + 2, length - 2);
            break;
        case 0x0023:
            ppp_ipv6_parser(ndo, p + 2, length - 2);
            break;
        default:
            ND_PRINT((ndo, "unknown protocol 0x%04x", proto));
            break;
    }
}
```