int _parseArgsList()

in src/apps/applib/lib/args.c [99:175]


int _parseArgsList(int argc, char* argv[], int numArgs, Arg* args[],
                   const Arg* helpArg, const char** errorMessage,
                   const char** errorDetail) {
    // Whether help was found and required arguments do not need to be checked
    bool foundHelp = false;

    for (int i = 1; i < argc; i++) {
        bool foundMatch = false;

        for (int j = 0; j < numArgs; j++) {
            // Test this argument, which may have multiple names, for whether it
            // matches. argName will be set to the name used for this argument
            // if it matches.
            const char* argName = NULL;
            for (int k = 0; k < NUM_ARG_NAMES; k++) {
                if (args[j]->names[k] == NULL) continue;

                if (strcmp(argv[i], args[j]->names[k]) == 0) {
                    argName = args[j]->names[k];
                    break;
                }
            }
            // argName unchanged from NULL indicates this didn't match, try the
            // next argument.
            if (argName == NULL) continue;

            if (args[j]->found) {
                *errorMessage = "Argument specified multiple times";
                *errorDetail = argName;
                return PARSE_ARGS_REPEATED_ARGUMENT;
            }

            if (args[j]->scanFormat != NULL) {
                // Argument has a value, need to advance one and read the value.
                i++;
                if (i >= argc) {
                    *errorMessage = "Argument value not present";
                    *errorDetail = argName;
                    return PARSE_ARGS_MISSING_VALUE;
                }

                if (!sscanf(argv[i], args[j]->scanFormat, args[j]->value)) {
                    *errorMessage = "Failed to parse argument";
                    *errorDetail = argName;
                    return PARSE_ARGS_FAILED_PARSE;
                }
            }

            if (args[j] == helpArg) {
                foundHelp = true;
            }

            args[j]->found = true;
            foundMatch = true;
            break;
        }

        if (!foundMatch) {
            *errorMessage = "Unknown argument";
            // Don't set errorDetail, since the input could be unprintable.
            return PARSE_ARGS_UNKNOWN_ARGUMENT;
        }
    }

    // Check for missing required arguments.
    if (!foundHelp) {
        for (int i = 0; i < numArgs; i++) {
            if (args[i]->required && !args[i]->found) {
                *errorMessage = "Required argument missing";
                *errorDetail = args[i]->names[0];
                return PARSE_ARGS_MISSING_REQUIRED;
            }
        }
    }

    return PARSE_ARGS_SUCCESS;
}