197 lines
4.6 KiB
C
197 lines
4.6 KiB
C
/**
|
|
* \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 <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include <assert.h>
|
|
#include <limits.h>
|
|
#include <getopt/getopt.h>
|
|
|
|
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");
|
|
}
|
|
}
|
|
}
|