1/** 2 * \file 3 * \brief Commandline parameter parsing. 4 */ 5 6/* 7 * Copyright (c) 2007, 2008, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdio.h> 16#include <string.h> 17#include <stdlib.h> 18#include <stdbool.h> 19#include <assert.h> 20#include <limits.h> 21#include <getopt/getopt.h> 22 23static int handle_ulong(unsigned long *var, const char *val) 24{ 25 assert(var != NULL); 26 int base; 27 28 // determine base (0x -> hex, anything else -> decimal) 29 if (val[0] == '0' && val[1] == 'x') { 30 base = 16; 31 val += 2; 32 } else { 33 base = 10; 34 } 35 36 unsigned long long x = strtoull(val, NULL, base); 37 if (x > ULONG_MAX) { 38 x = ULONG_MAX; 39 } 40 *var = (unsigned long)x; 41 return 0; 42} 43 44static int handle_long(long *var, const char *val) 45{ 46 assert(var != NULL); 47 int base; 48 49 // determine base (0x -> hex, anything else -> decimal) 50 if (val[0] == '0' && val[1] == 'x') { 51 base = 16; 52 val += 2; 53 } else { 54 base = 10; 55 } 56 57 long long x = strtoll(val, NULL, base); 58 assert(x >= LONG_MIN && x <= LONG_MAX); // XXX 59 *var = x; 60 61 return 0; 62} 63 64static int handle_uint(unsigned int *var, const char *val) 65{ 66 assert(var != NULL); 67 int base; 68 69 // determine base (0x -> hex, anything else -> decimal) 70 if (val[0] == '0' && val[1] == 'x') { 71 base = 16; 72 val += 2; 73 } else { 74 base = 10; 75 } 76 77 unsigned long x = strtoul(val, NULL, base); 78 if (x > UINT_MAX) { 79 x = UINT_MAX; 80 } 81 *var = (unsigned)x; 82 return 0; 83} 84 85static int handle_int(int *var, const char *val) 86{ 87 assert(var != NULL); 88 int base; 89 90 // determine base (0x -> hex, anything else -> decimal) 91 if (val[0] == '0' && val[1] == 'x') { 92 base = 16; 93 val += 2; 94 } else { 95 base = 10; 96 } 97 98 long x = strtol(val, NULL, base); 99 assert(x >= INT_MIN && x <= INT_MAX); // XXX 100 *var = (int)x; 101 102 return 0; 103} 104 105static int handle_bool(bool *var, const char *val) 106{ 107 assert(var != NULL); 108 if(!strncmp(val, "true", 4) || !strncmp(val, "yes", 3)) { 109 *var = true; 110 return 0; 111 } else if(!strncmp(val, "false", 5) || !strncmp(val, "no", 2)) { 112 *var = false; 113 return 0; 114 } 115 116 return -1; 117} 118 119static int handle_argument(const char *var, const char *val, 120 struct cmdarg *cmdargs) 121{ 122 // compare var against array of recognized arguments 123 for(int i = 0; cmdargs[i].arg != NULL; i++) { 124 struct cmdarg *a = &cmdargs[i]; 125 if(!strncmp(var, a->arg, strlen(a->arg))) { 126 switch(a->type) { 127 case ArgType_Int: 128 return handle_int(a->var.integer, val); 129 130 case ArgType_UInt: 131 return handle_uint(a->var.uinteger, val); 132 133 case ArgType_Long: 134 return handle_long(a->var.longinteger, val); 135 136 case ArgType_ULong: 137 return handle_ulong(a->var.ulonginteger, val); 138 139 case ArgType_Bool: 140 return handle_bool(a->var.boolean, val); 141 142 case ArgType_Custom: 143 return a->var.handler(var, val); 144 145 default: 146 assert(!"Unknown type %d in kernel argument array!"); 147 return -1; 148 } 149 } 150 } 151 152 return 0; 153} 154 155/** 156 * \brief Search backwards for character 'c' in string 'p'. 157 * 158 * Starts at the character, pointed to by 'p', within a string and searches 159 * backwards for 'c', returning a pointer to its position. 160 * 161 * WARNING: 'c' MUST exist prior to calling this function!! 162 * 163 * \param p Character to start searching backwards from. 164 * \param c Character to look for. 165 * 166 * \return Pointer to 'c' in string. 167 */ 168static const char *look_back(const char *p, int c) 169{ 170 while(*p != c) { 171 p--; 172 } 173 174 return p; 175} 176 177/** 178 * \brief Parse commandline parameters in 'cmdline'. 179 * 180 * Parses 'cmdline' for kernel commandline parameters and sets configuration 181 * variables accordingly. 182 * 183 * \param cmdline Kernel commandline string. 184 */ 185void parse_commandline(const char *cmdline, struct cmdarg *cmdargs) 186{ 187 // Parse argument string into whitespace-separated 'var=val' tokens 188 for(const char *p = strchr(cmdline, '='); p != NULL; 189 p = strchr(p + 1, '=')) { 190 const char *var = look_back(p, ' ') + 1, *val = p + 1; 191 192 if(handle_argument(var, val, cmdargs) != 0) { 193 assert(!"parse_commandline: Parse error in commandline"); 194 } 195 } 196} 197