Home | History | Annotate | Download | only in sanitizer_common
      1 //===-- sanitizer_flags.cc ------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "sanitizer_flags.h"
     15 
     16 #include "sanitizer_common.h"
     17 #include "sanitizer_libc.h"
     18 
     19 namespace __sanitizer {
     20 
     21 static bool GetFlagValue(const char *env, const char *name,
     22                          const char **value, int *value_length) {
     23   if (env == 0)
     24     return false;
     25   const char *pos = internal_strstr(env, name);
     26   const char *end;
     27   if (pos == 0)
     28     return false;
     29   pos += internal_strlen(name);
     30   if (pos[0] != '=') {
     31     end = pos;
     32   } else {
     33     pos += 1;
     34     if (pos[0] == '"') {
     35       pos += 1;
     36       end = internal_strchr(pos, '"');
     37     } else if (pos[0] == '\'') {
     38       pos += 1;
     39       end = internal_strchr(pos, '\'');
     40     } else {
     41       // Read until the next space or colon.
     42       end = pos + internal_strcspn(pos, " :");
     43     }
     44     if (end == 0)
     45       end = pos + internal_strlen(pos);
     46   }
     47   *value = pos;
     48   *value_length = end - pos;
     49   return true;
     50 }
     51 
     52 static bool StartsWith(const char *flag, int flag_length, const char *value) {
     53   if (!flag || !value)
     54     return false;
     55   int value_length = internal_strlen(value);
     56   return (flag_length >= value_length) &&
     57          (0 == internal_strncmp(flag, value, value_length));
     58 }
     59 
     60 void ParseFlag(const char *env, bool *flag, const char *name) {
     61   const char *value;
     62   int value_length;
     63   if (!GetFlagValue(env, name, &value, &value_length))
     64     return;
     65   if (StartsWith(value, value_length, "0") ||
     66       StartsWith(value, value_length, "no") ||
     67       StartsWith(value, value_length, "false"))
     68     *flag = false;
     69   if (StartsWith(value, value_length, "1") ||
     70       StartsWith(value, value_length, "yes") ||
     71       StartsWith(value, value_length, "true"))
     72     *flag = true;
     73 }
     74 
     75 void ParseFlag(const char *env, int *flag, const char *name) {
     76   const char *value;
     77   int value_length;
     78   if (!GetFlagValue(env, name, &value, &value_length))
     79     return;
     80   *flag = internal_atoll(value);
     81 }
     82 
     83 static LowLevelAllocator allocator_for_flags;
     84 
     85 void ParseFlag(const char *env, const char **flag, const char *name) {
     86   const char *value;
     87   int value_length;
     88   if (!GetFlagValue(env, name, &value, &value_length))
     89     return;
     90   // Copy the flag value. Don't use locks here, as flags are parsed at
     91   // tool startup.
     92   char *value_copy = (char*)(allocator_for_flags.Allocate(value_length + 1));
     93   internal_memcpy(value_copy, value, value_length);
     94   value_copy[value_length] = '\0';
     95   *flag = value_copy;
     96 }
     97 
     98 }  // namespace __sanitizer
     99