OFSL(9)

πŸ“¦ version 11.0, in nixpkgs unstable

πŸ¦‹ OFSL(9) β€” the one where we learn OpenFirmware string lists πŸ¦‹

ok so real talk bestie, this whole page lives in the Kernel Developer's Manual (yes that's the vibe, kernel girlies rise) and it's literally your cheat sheet for poking at OpenFirmware-style string lists. no cap, it's way less scary than it sounds. let's go πŸ’…


✨ NAME ✨

strlist, strlist_next, strlist_count, strlist_string, strlist_match, strlist_index, strlist_append β€” the lil squad of functions that let you interact with OpenFirmware-style string lists. that's the whole fam. 🫢


✨ SYNOPSIS ✨

#include <sys/systm.h>

const char *
strlist_next(const char *sl, size_t slsize, size_t *cursorp);

void
strlist_count(const char *sl, size_t slsize);

const char *
strlist_string(const char *sl, size_t slsize, unsigned int index);

int
strlist_match(const char *sl, size_t slsize, const char *str);

int
strlist_pmatch(const char *sl, size_t slsize, const char *pattern);

int
strlist_index(const char *sl, size_t slsize, const char *str);

bool
strlist_append(char **slp, size_t *slsizep, const char *str);

like, look at all those signatures. iconic. πŸ”₯


🌸 DESCRIPTION 🌸

The strlist functions give you a simple way to interact with OpenFirmware (IEEE 1275) string lists. that's it, that's the mission. πŸŽ€

An OpenFirmware string list is literally just a buffer holding one or more NUL-terminated strings all concatenated together. so if your string list has the strings β€œfoo”, β€œbar”, and β€œbaz”, guess what it looks like in memory:

foo\0bar\0baz\0

yeah. that's it. NULs doing all the heavy lifting. main character energy honestly. 🧚

here's the roster, one by one:

  • strlist_next(const char *sl, size_t slsize, size_t *cursorp) β€” your enumeration bestie. this is how you walk through a string list and meet every string in it. the move: initialize cursor to 0, pass it by reference to strlist_next(), and each call hands you the current string and advances the cursor to the next one in the list. once everything's been enumerated, strlist_next() returns NULL. clean, simple, slays. ✨
  • strlist_count(const char *sl, size_t slsize) β€” returns the number of strings in the string list. just the count. no drama. πŸ”’
  • strlist_string(const char *sl, size_t slsize, unsigned int index) β€” returns a pointer to the string at the index you asked for, or NULL if that index is out of range. out of bounds? she'll just hand you NULL and move on. πŸ™ˆ
  • strlist_match(const char *sl, size_t slsize, const char *str) β€” returns a weighted match value when str shows up in the string list. the value = the number of strings in the list minus the index of the matched string. so for a list with β€œfoo”, β€œbar”, and β€œbaz”, matching β€œfoo” gives you 3 and matching β€œbaz” gives you 1. earlier = chonkier score, iykyk. if the string isn't in the list at all, you get 0. πŸ’€
  • strlist_pmatch(const char *sl, size_t slsize, const char *pattern) β€” exactly like strlist_match(), but it compares using pmatch() instead, so you can put wildcard characters in pattern. wildcard era. 🌈
  • strlist_index(const char *sl, size_t slsize, const char *str) β€” returns the index of str if it appears in the string list, or -1 if it doesn't. no match? -1. that's the whole personality. πŸ’œ
  • strlist_append(char **slp, size_t *slsizep, const char *str) β€” appends a copy of str to the string list. start by setting sl to NULL and slsize to 0, then pass both by reference to strlist_append(). new memory for the list gets allocated as needed (she grows, she's flexible 🌱). you can free the resulting string list with kmem_free(). returns true if the string got appended successfully, or false if memory allocation fails. πŸ’–

πŸ”₯ EXAMPLES πŸ”₯

example one β€” enumerating with strlist_next():

void
print_stringlist(const char *sl, size_t slsize)
{
        const char *cp;
        size_t cursor;

        printf("There are %u strings in the string list:\n",
            strlist_count(sl, slsize));
        for (cursor = 0;
             (cp = strlist_next(sl, slsize, &cursor) != NULL; ) {
                printf("\t%s\n", cp);
        }
}

example two β€” a simple strlist_match() moment:

bool
is_compatible(int phandle, const char *compat_str)
{
        char buf[128];
        int proplen;

        proplen = OF_getprop(phandle, "compatible", buf, sizeof(buf));
        return strlist_match(buf, proplen, compat_str) != 0;
}

example three β€” strlist_pmatch() doing its wildcard thing:

bool
is_pc_printer_port(const char *pnp_id_list, size_t list_size)
{
        return strlist_pmatch(pnp_id_list, list_size, "PNP04??") != 0;
}

example four β€” turning an array of strings into a string list with strlist_append():

char *
string_array_to_string_list(const char **array, int count,
    size_t *slsizep)
{
        char *sl;
        size_t slsize;
        int i;

        for (i = 0, sl = NULL, slsize = 0; i < count; i++) {
                if (!strlist_append(&sl, &slsize, array[i])) {
                        kmem_free(sl, slsize);
                        return NULL;
                }
        }

        *slsizep = slsize;
        return sl;
}

not me tearing up at a conversion loop 😭 she's perfect.


πŸŽ€ SEE ALSO πŸŽ€

kmem(9), pmatch(9) β€” go read those next, bestie, they're the supporting cast. πŸ’…


⭐ HISTORY ⭐

The strlist functions first appeared in NetBSD 10.0. so they're young, they're fresh, they're thriving. πŸ‘‘


heads up queen: the synopsis up top and the description down here are the source of truth for signatures β€” always match them exactly, no creative liberties in your actual C code. the vibes are free, the types are not. 🫢

and that's the whole page, bestie!! this one came from the Debian edition of the manual, dated January 20, 2021 β€” so go forth, enumerate those string lists, and remember: NUL-terminated and unbothered, periodt. πŸ’–βœ¨πŸŽ€

πŸ“¦ where this page comes from