aboutsummaryrefslogtreecommitdiffstats
path: root/android/cmdline-option.c
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:30:32 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:30:32 -0800
commit8b23a6c7e1aee255004dd19098d4c2462b61b849 (patch)
tree7a4d682ba51f0ff0364c5ca2509f515bdaf96de9 /android/cmdline-option.c
parentf721e3ac031f892af46f255a47d7f54a91317b30 (diff)
downloadexternal_qemu-8b23a6c7e1aee255004dd19098d4c2462b61b849.zip
external_qemu-8b23a6c7e1aee255004dd19098d4c2462b61b849.tar.gz
external_qemu-8b23a6c7e1aee255004dd19098d4c2462b61b849.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'android/cmdline-option.c')
-rw-r--r--android/cmdline-option.c255
1 files changed, 255 insertions, 0 deletions
diff --git a/android/cmdline-option.c b/android/cmdline-option.c
new file mode 100644
index 0000000..b773d9d
--- /dev/null
+++ b/android/cmdline-option.c
@@ -0,0 +1,255 @@
+#include "android/cmdline-option.h"
+#include "android/utils/debug.h"
+#include "android/utils/misc.h"
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+#define _VERBOSE_TAG(x,y) { #x, VERBOSE_##x, y },
+static const struct { const char* name; int flag; const char* text; }
+debug_tags[] = {
+ VERBOSE_TAG_LIST
+ { 0, 0, 0 }
+};
+
+static void parse_debug_tags( const char* tags );
+void parse_env_debug_tags( void );
+
+
+typedef struct {
+ const char* name;
+ int var_offset;
+ int var_is_param;
+ int var_is_config;
+} OptionInfo;
+
+#define OPTION(_name,_type,_config) \
+ { #_name, offsetof(AndroidOptions,_name), _type, _config },
+
+
+static const OptionInfo option_keys[] = {
+#define OPT_PARAM(_name,_template,_descr) OPTION(_name,1,0)
+#define OPT_FLAG(_name,_descr) OPTION(_name,0,0)
+#define CFG_PARAM(_name,_template,_descr) OPTION(_name,1,1)
+#define CFG_FLAG(_name,_descr) OPTION(_name,0,1)
+#include "android/cmdline-options.h"
+ { NULL, 0, 0, 0 }
+};
+
+int
+android_parse_options( int *pargc, char** *pargv, AndroidOptions* opt )
+{
+ int nargs = *pargc-1;
+ char** aread = *pargv+1;
+ char** awrite = aread;
+
+ memset( opt, 0, sizeof *opt );
+
+ while (nargs > 0) {
+ char* arg;
+ char arg2_tab[64], *arg2 = arg2_tab;
+ int nn;
+
+ /* process @<name> as a special exception meaning
+ * '-avd <name>'
+ */
+ if (aread[0][0] == '@') {
+ opt->avd = aread[0]+1;
+ nargs--;
+ aread++;
+ continue;
+ }
+
+ /* anything that isn't an option past this points
+ * exits the loop
+ */
+ if (aread[0][0] != '-') {
+ break;
+ }
+
+ arg = aread[0]+1;
+
+ /* an option cannot contain an underscore */
+ if (strchr(arg, '_') != NULL) {
+ break;
+ }
+
+ nargs--;
+ aread++;
+
+ /* for backwards compatibility with previous versions */
+ if (!strcmp(arg, "verbose")) {
+ arg = "debug-init";
+ }
+
+ /* special handing for -debug <tags> */
+ if (!strcmp(arg, "debug")) {
+ if (nargs == 0) {
+ derror( "-debug must be followed by tags (see -help-verbose)\n");
+ exit(1);
+ }
+ nargs--;
+ parse_debug_tags(*aread++);
+ continue;
+ }
+
+ /* NOTE: variable tables map option names to values
+ * (e.g. field offsets into the AndroidOptions structure).
+ *
+ * however, the names stored in the table used underscores
+ * instead of dashes. this means that the command-line option
+ * '-foo-bar' will be associated to the name 'foo_bar' in
+ * this table, and will point to the field 'foo_bar' or
+ * AndroidOptions.
+ *
+ * as such, before comparing the current option to the
+ * content of the table, we're going to translate dashes
+ * into underscores.
+ */
+ arg2 = arg2_tab;
+ buffer_translate_char( arg2_tab, sizeof(arg2_tab),
+ arg, '-', '_');
+
+ /* special handling for -debug-<tag> and -debug-no-<tag> */
+ if (!memcmp(arg2, "debug_", 6)) {
+ int remove = 0;
+ unsigned long mask = 0;
+ arg2 += 6;
+ if (!memcmp(arg2, "no_", 3)) {
+ arg2 += 3;
+ remove = 1;
+ }
+ if (!strcmp(arg2, "all")) {
+ mask = ~0;
+ }
+ for (nn = 0; debug_tags[nn].name; nn++) {
+ if (!strcmp(arg2, debug_tags[nn].name)) {
+ mask = (1UL << debug_tags[nn].flag);
+ break;
+ }
+ }
+ if (remove)
+ android_verbose &= ~mask;
+ else
+ android_verbose |= mask;
+ continue;
+ }
+
+ /* look into our table of options
+ *
+ */
+ {
+ const OptionInfo* oo = option_keys;
+
+ for ( ; oo->name; oo++ ) {
+ if ( !strcmp( oo->name, arg2 ) ) {
+ void* field = (char*)opt + oo->var_offset;
+
+ if (oo->var_is_param) {
+ /* parameter option */
+ if (nargs == 0) {
+ derror( "-%s must be followed by parameter (see -help-%s)",
+ arg, arg );
+ exit(1);
+ }
+ nargs--;
+ ((char**)field)[0] = *aread++;
+ } else {
+ /* flag option */
+ ((int*)field)[0] = 1;
+ }
+ break;
+ }
+ }
+
+ if (oo->name == NULL) { /* unknown option ? */
+ nargs++;
+ aread--;
+ break;
+ }
+ }
+ }
+
+ /* copy remaining parameters, if any, to command line */
+ *pargc = nargs + 1;
+
+ while (nargs > 0) {
+ awrite[0] = aread[0];
+ awrite ++;
+ aread ++;
+ nargs --;
+ }
+
+ awrite[0] = NULL;
+
+ return 0;
+}
+
+
+
+/* special handling of -debug option and tags */
+#define ENV_DEBUG "ANDROID_DEBUG"
+
+static void
+parse_debug_tags( const char* tags )
+{
+ char* x;
+ char* y;
+ char* x0;
+
+ if (tags == NULL)
+ return;
+
+ x = x0 = strdup(tags);
+ while (*x) {
+ y = strchr(x, ',');
+ if (y == NULL)
+ y = x + strlen(x);
+ else
+ *y++ = 0;
+
+ if (y > x+1) {
+ int nn, remove = 0;
+ unsigned mask = 0;
+
+ if (x[0] == '-') {
+ remove = 1;
+ x += 1;
+ }
+
+ if (!strcmp( "all", x ))
+ mask = ~0;
+ else {
+ char temp[32];
+ buffer_translate_char(temp, sizeof temp, x, '-', '_');
+
+ for (nn = 0; debug_tags[nn].name != NULL; nn++) {
+ if ( !strcmp( debug_tags[nn].name, temp ) ) {
+ mask |= (1 << debug_tags[nn].flag);
+ break;
+ }
+ }
+ }
+
+ if (mask == 0)
+ dprint( "ignoring unknown " ENV_DEBUG " item '%s'", x );
+ else {
+ if (remove)
+ android_verbose &= ~mask;
+ else
+ android_verbose |= mask;
+ }
+ }
+ x = y;
+ }
+
+ free(x0);
+}
+
+void
+parse_env_debug_tags( void )
+{
+ const char* env = getenv( ENV_DEBUG );
+ parse_debug_tags( env );
+}
+