1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/* 2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle 3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2006, Google Inc. 4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without 6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met: 7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 1. Redistributions of source code must retain the above copyright notice, 9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer. 10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 2. Redistributions in binary form must reproduce the above copyright notice, 11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer in the documentation 12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * and/or other materials provided with the distribution. 13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 3. The name of the author may not be used to endorse or promote products 14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * derived from this software without specific prior written permission. 15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */ 27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <stdio.h> 29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <stdlib.h> 30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <string.h> 31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32 34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/win32.h" 35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <shellapi.h> 36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 38f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/flags.h" 39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// ----------------------------------------------------------------------------- 42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Implementation of Flag 43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochFlag::Flag(const char* file, const char* name, const char* comment, 45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Type type, void* variable, FlagValue default__) 46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch : file_(file), 47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch name_(name), 48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch comment_(comment), 49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch type_(type), 50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch variable_(reinterpret_cast<FlagValue*>(variable)), 51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch default_(default__) { 52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch FlagList::Register(this); 53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Flag::SetToDefault() { 57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Note that we cannot simply do '*variable_ = default_;' since 58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // flag variables are not really of type FlagValue and thus may 59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // be smaller! The FlagValue union is simply 'overlayed' on top 60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // of a flag variable for convenient access. Since union members 61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // are guarantee to be aligned at the beginning, this works. 62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch switch (type_) { 63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case Flag::BOOL: 64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch variable_->b = default_.b; 65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case Flag::INT: 67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch variable_->i = default_.i; 68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case Flag::FLOAT: 70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch variable_->f = default_.f; 71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case Flag::STRING: 73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch variable_->s = default_.s; 74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UNREACHABLE(); 77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic const char* Type2String(Flag::Type type) { 81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch switch (type) { 82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case Flag::BOOL: return "bool"; 83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case Flag::INT: return "int"; 84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case Flag::FLOAT: return "float"; 85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case Flag::STRING: return "string"; 86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UNREACHABLE(); 88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic void PrintFlagValue(Flag::Type type, FlagValue* p) { 93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch switch (type) { 94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case Flag::BOOL: 95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch printf("%s", (p->b ? "true" : "false")); 96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case Flag::INT: 98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch printf("%d", p->i); 99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case Flag::FLOAT: 101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch printf("%f", p->f); 102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case Flag::STRING: 104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch printf("%s", p->s); 105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UNREACHABLE(); 108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Flag::Print(bool print_current_value) { 112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch printf(" --%s (%s) type: %s default: ", name_, comment_, 113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Type2String(type_)); 114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch PrintFlagValue(type_, &default_); 115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (print_current_value) { 116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch printf(" current value: "); 117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch PrintFlagValue(type_, variable_); 118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch printf("\n"); 120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// ----------------------------------------------------------------------------- 124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Implementation of FlagList 125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochFlag* FlagList::list_ = NULL; 127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochFlagList::FlagList() { 130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch list_ = NULL; 131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid FlagList::Print(const char* file, bool print_current_value) { 134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Since flag registration is likely by file (= C++ file), 135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // we don't need to sort by file and still get grouped output. 136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const char* current = NULL; 137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (Flag* f = list_; f != NULL; f = f->next()) { 138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (file == NULL || file == f->file()) { 139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (current != f->file()) { 140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch printf("Flags from %s:\n", f->file()); 141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch current = f->file(); 142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch f->Print(print_current_value); 144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochFlag* FlagList::Lookup(const char* name) { 150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Flag* f = list_; 151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch while (f != NULL && strcmp(name, f->name()) != 0) 152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch f = f->next(); 153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return f; 154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid FlagList::SplitArgument(const char* arg, 158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch char* buffer, int buffer_size, 159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const char** name, const char** value, 160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool* is_bool) { 161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *name = NULL; 162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *value = NULL; 163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *is_bool = false; 164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (*arg == '-') { 166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // find the begin of the flag name 167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch arg++; // remove 1st '-' 168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (*arg == '-') 169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch arg++; // remove 2nd '-' 170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (arg[0] == 'n' && arg[1] == 'o') { 171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch arg += 2; // remove "no" 172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *is_bool = true; 173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *name = arg; 175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // find the end of the flag name 177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch while (*arg != '\0' && *arg != '=') 178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch arg++; 179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // get the value if any 181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (*arg == '=') { 182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // make a copy so we can NUL-terminate flag name 183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int n = arg - *name; 184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (n >= buffer_size) 185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Fatal(__FILE__, __LINE__, "CHECK(%s) failed", "n < buffer_size"); 186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch memcpy(buffer, *name, n * sizeof(char)); 187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buffer[n] = '\0'; 188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *name = buffer; 189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // get the value 190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *value = arg + 1; 191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint FlagList::SetFlagsFromCommandLine(int* argc, const char** argv, 197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool remove_flags) { 198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // parse arguments 199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (int i = 1; i < *argc; /* see below */) { 200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int j = i; // j > 0 201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const char* arg = argv[i++]; 202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // split arg into flag components 204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch char buffer[1024]; 205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const char* name; 206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const char* value; 207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool is_bool; 208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SplitArgument(arg, buffer, sizeof buffer, &name, &value, &is_bool); 209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (name != NULL) { 211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // lookup the flag 212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Flag* flag = Lookup(name); 213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (flag == NULL) { 214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch fprintf(stderr, "Error: unrecognized flag %s\n", arg); 215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return j; 216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // if we still need a flag value, use the next argument if available 219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (flag->type() != Flag::BOOL && value == NULL) { 220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (i < *argc) { 221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch value = argv[i++]; 222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch fprintf(stderr, "Error: missing value for flag %s of type %s\n", 224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch arg, Type2String(flag->type())); 225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return j; 226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // set the flag 230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch char empty[] = { '\0' }; 231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch char* endp = empty; 232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch switch (flag->type()) { 233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case Flag::BOOL: 234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *flag->bool_variable() = !is_bool; 235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case Flag::INT: 237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *flag->int_variable() = strtol(value, &endp, 10); 238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case Flag::FLOAT: 240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *flag->float_variable() = strtod(value, &endp); 241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case Flag::STRING: 243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *flag->string_variable() = value; 244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // handle errors 248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ((flag->type() == Flag::BOOL && value != NULL) || 249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch (flag->type() != Flag::BOOL && is_bool) || 250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *endp != '\0') { 251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch fprintf(stderr, "Error: illegal value for flag %s of type %s\n", 252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch arg, Type2String(flag->type())); 253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return j; 254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // remove the flag & value from the command 257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (remove_flags) 258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch while (j < i) 259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch argv[j++] = NULL; 260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // shrink the argument list 264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (remove_flags) { 265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int j = 1; 266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (int i = 1; i < *argc; i++) { 267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (argv[i] != NULL) 268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch argv[j++] = argv[i]; 269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *argc = j; 271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 272f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // parsed all flags successfully 274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return 0; 275f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 276f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 277f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid FlagList::Register(Flag* flag) { 278f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch assert(flag != NULL && strlen(flag->name()) > 0); 279f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (Lookup(flag->name()) != NULL) 280f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Fatal(flag->file(), 0, "flag %s declared twice", flag->name()); 281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch flag->next_ = list_; 282f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch list_ = flag; 283f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 284f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 285f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32 286f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochWindowsCommandLineArguments::WindowsCommandLineArguments() { 287f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // start by getting the command line. 288f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LPTSTR command_line = ::GetCommandLine(); 289f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // now, convert it to a list of wide char strings. 290f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LPWSTR *wide_argv = ::CommandLineToArgvW(command_line, &argc_); 291f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // now allocate an array big enough to hold that many string pointers. 292f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch argv_ = new char*[argc_]; 293f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 294f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // iterate over the returned wide strings; 295f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for(int i = 0; i < argc_; ++i) { 296f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // for each, create a char buffer big enough to hold it; so, find out 297f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // how much space we need. 298f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int len8 = WideCharToMultiByte(CP_UTF8, 0, wide_argv[i], 299f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch wcslen(wide_argv[i]), NULL, 0, 300f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch NULL, NULL); 301f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // then allocate the buffer... 302f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch char *buffer = new char[1 + len8]; // +1 for trailing \0 303f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // and do the conversion. 304f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch WideCharToMultiByte(CP_UTF8, 0, wide_argv[i], 305f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch wcslen(wide_argv[i]), buffer, len8, 306f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch NULL, NULL); 307f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // WideCharToMultibyte doesn't give us a trailing \0, so we add it. 308f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buffer[len8] = '\0'; 309f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // make sure the argv array has the right string at this point. 310f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch argv_[i] = buffer; 311f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 312f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LocalFree(wide_argv); 313f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 314f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 315f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochWindowsCommandLineArguments::~WindowsCommandLineArguments() { 316f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // need to free each string in the array, and then the array. 317f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for(int i = 0; i < argc_; i++) { 318f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete[] argv_[i]; 319f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 320f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 321f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete[] argv_; 322f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 323f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif // WIN32 324f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 325