diff --git a/headers/posix/stdlib.h b/headers/posix/stdlib.h index 0544c8af2e..cdb1b3838d 100644 --- a/headers/posix/stdlib.h +++ b/headers/posix/stdlib.h @@ -168,6 +168,9 @@ extern size_t wcstombs(char *string, const wchar_t *pwcs, size_t maxSize); /* crypt */ extern void setkey(const char *key); +/* sub-option parsing */ +extern int getsubopt(char **optionp, char * const *keylistp, + char **valuep); /* pty functions */ extern int posix_openpt(int openFlags); diff --git a/src/system/libroot/posix/stdlib/Jamfile b/src/system/libroot/posix/stdlib/Jamfile index 5983951358..dd2711e0ad 100644 --- a/src/system/libroot/posix/stdlib/Jamfile +++ b/src/system/libroot/posix/stdlib/Jamfile @@ -12,6 +12,7 @@ MergeObject posix_stdlib.o : div.c env.cpp exit.c + getsubopt.cpp heapsort.c merge.c mktemp.c diff --git a/src/system/libroot/posix/stdlib/getsubopt.cpp b/src/system/libroot/posix/stdlib/getsubopt.cpp new file mode 100644 index 0000000000..9346bcef32 --- /dev/null +++ b/src/system/libroot/posix/stdlib/getsubopt.cpp @@ -0,0 +1,39 @@ +/* + * Copyright 2010, Oliver Tappe . + * Distributed under the terms of the MIT License. + */ + + +#include +#include + + +int +getsubopt(char** optionPtr, char* const* keys, char** valuePtr) +{ + if (optionPtr == NULL || valuePtr == NULL) + return -1; + + char* option = *optionPtr; + if (*option == '\0') + return -1; + + char* startOfNextOption = strchr(option, ','); + if (startOfNextOption != NULL) + *startOfNextOption++ = '\0'; + else + startOfNextOption = option + strlen(option); + *optionPtr = startOfNextOption; + + char* startOfValue = strchr(option, '='); + if (startOfValue != NULL) + *startOfValue++ = '\0'; + *valuePtr = startOfValue; + + for (int keyIndex = 0; keys[keyIndex] != NULL; ++keyIndex) { + if (strcmp(option, keys[keyIndex]) == 0) + return keyIndex; + } + + return -1; +} diff --git a/src/tests/system/libroot/posix/Jamfile b/src/tests/system/libroot/posix/Jamfile index 4b83b2f42e..aced757751 100644 --- a/src/tests/system/libroot/posix/Jamfile +++ b/src/tests/system/libroot/posix/Jamfile @@ -12,6 +12,7 @@ SimpleTest SyslogTest : SyslogTest.cpp syslog.cpp ; SimpleTest clearenv : clearenv.cpp ; SimpleTest dirent_test : dirent_test.cpp ; SimpleTest flock_test : flock_test.cpp ; +SimpleTest getsubopt_test : getsubopt_test.cpp ; SimpleTest locale_test : locale_test.cpp ; SimpleTest memalign_test : memalign_test.cpp ; SimpleTest mprotect_test : mprotect_test.cpp ; diff --git a/src/tests/system/libroot/posix/getsubopt_test.cpp b/src/tests/system/libroot/posix/getsubopt_test.cpp new file mode 100644 index 0000000000..6a2c56e745 --- /dev/null +++ b/src/tests/system/libroot/posix/getsubopt_test.cpp @@ -0,0 +1,38 @@ +/* + * Copyright 2010, Oliver Tappe . + * Distributed under the terms of the MIT License. + */ + + +#include +#include +#include + + +int +main() +{ + char* const keys[] = { + "mode", "be-lenient", NULL + }; + + char* option = strdup("mode=readwrite,unknown,be-lenient"); + char* value = NULL; + int result = getsubopt(&option, keys, &value); + if (result != 0) + fprintf(stderr, "failed 1: result=%d, expected %d\n", result, 0); + if (value == NULL || strcmp(value, "readwrite") != 0) + fprintf(stderr, "failed 2: value=%s, expected 'readwrite'\n", value); + result = getsubopt(&option, keys, &value); + if (result != -1) + fprintf(stderr, "failed 3: result=%d, expected %d\n", result, -1); + if (value != NULL) + fprintf(stderr, "failed 4: value=%p, expected NULL\n", value); + result = getsubopt(&option, keys, &value); + if (result != 1) + fprintf(stderr, "failed 5: result=%d, expected %d\n", result, 1); + if (value != NULL) + fprintf(stderr, "failed 6: value=%p, expected NULL\n", value); + + return 0; +}