/** * \file * \brief Commandline parameter parsing. */ /* * Copyright (c) 2007, 2008, ETH Zurich. * All rights reserved. * * This file is distributed under the terms in the attached LICENSE file. * If you do not find this file, copies can be found by writing to: * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. */ #include #include #include #include #include #include #include static int handle_ulong(unsigned long *var, const char *val) { assert(var != NULL); int base; // determine base (0x -> hex, anything else -> decimal) if (val[0] == '0' && val[1] == 'x') { base = 16; val += 2; } else { base = 10; } unsigned long long x = strtoull(val, NULL, base); if (x > ULONG_MAX) { x = ULONG_MAX; } *var = (unsigned long)x; return 0; } static int handle_long(long *var, const char *val) { assert(var != NULL); int base; // determine base (0x -> hex, anything else -> decimal) if (val[0] == '0' && val[1] == 'x') { base = 16; val += 2; } else { base = 10; } long long x = strtoll(val, NULL, base); assert(x >= LONG_MIN && x <= LONG_MAX); // XXX *var = x; return 0; } static int handle_uint(unsigned int *var, const char *val) { assert(var != NULL); int base; // determine base (0x -> hex, anything else -> decimal) if (val[0] == '0' && val[1] == 'x') { base = 16; val += 2; } else { base = 10; } unsigned long x = strtoul(val, NULL, base); if (x > UINT_MAX) { x = UINT_MAX; } *var = (unsigned)x; return 0; } static int handle_int(int *var, const char *val) { assert(var != NULL); int base; // determine base (0x -> hex, anything else -> decimal) if (val[0] == '0' && val[1] == 'x') { base = 16; val += 2; } else { base = 10; } long x = strtol(val, NULL, base); assert(x >= INT_MIN && x <= INT_MAX); // XXX *var = (int)x; return 0; } static int handle_bool(bool *var, const char *val) { assert(var != NULL); if(!strncmp(val, "true", 4) || !strncmp(val, "yes", 3)) { *var = true; return 0; } else if(!strncmp(val, "false", 5) || !strncmp(val, "no", 2)) { *var = false; return 0; } return -1; } static int handle_argument(const char *var, const char *val, struct cmdarg *cmdargs) { // compare var against array of recognized arguments for(int i = 0; cmdargs[i].arg != NULL; i++) { struct cmdarg *a = &cmdargs[i]; if(!strncmp(var, a->arg, strlen(a->arg))) { switch(a->type) { case ArgType_Int: return handle_int(a->var.integer, val); case ArgType_UInt: return handle_uint(a->var.uinteger, val); case ArgType_Long: return handle_long(a->var.longinteger, val); case ArgType_ULong: return handle_ulong(a->var.ulonginteger, val); case ArgType_Bool: return handle_bool(a->var.boolean, val); case ArgType_Custom: return a->var.handler(var, val); default: assert(!"Unknown type %d in kernel argument array!"); return -1; } } } return 0; } /** * \brief Search backwards for character 'c' in string 'p'. * * Starts at the character, pointed to by 'p', within a string and searches * backwards for 'c', returning a pointer to its position. * * WARNING: 'c' MUST exist prior to calling this function!! * * \param p Character to start searching backwards from. * \param c Character to look for. * * \return Pointer to 'c' in string. */ static const char *look_back(const char *p, int c) { while(*p != c) { p--; } return p; } /** * \brief Parse commandline parameters in 'cmdline'. * * Parses 'cmdline' for kernel commandline parameters and sets configuration * variables accordingly. * * \param cmdline Kernel commandline string. */ void parse_commandline(const char *cmdline, struct cmdarg *cmdargs) { // Parse argument string into whitespace-separated 'var=val' tokens for(const char *p = strchr(cmdline, '='); p != NULL; p = strchr(p + 1, '=')) { const char *var = look_back(p, ' ') + 1, *val = p + 1; if(handle_argument(var, val, cmdargs) != 0) { assert(!"parse_commandline: Parse error in commandline"); } } }