This content is not currently approved and is visible here for review only.

Library tutorials & articles

The use of the code analysis library OpenC++: modifications, improvements, error corrections

5. Getting values of numerical literals.

The function of getting a value of a numerical literal may be useful in systems of building documentation on the code. For example, with its help one may see that the argument of "void foo(a = 99)" function is 99 and use this for some purpose.

GetLiteralType() function that we offer allows to get the literal type and its value if it is integer. GetLiteralType() function is created for getting information needed most often and doesn't support rarely used record types. But if you need to support UCNs for example or get values of double type, you may expand functionality of the functions given below by yourself.

unsigned __int64 GetHexValue(unsigned char c) {
  if (c >= '0' && c <= '9')
    return c - '0';
  if (c >= 'a' && c <= 'f')
    return c - 'a' + 0x0a;
  if (c >= 'A' && c <= 'F')
    return c - 'A' + 0x0a;
  assert(false);
  return 0;
}	
bool GetHex(const char *&from, size_t len,
            unsigned __int64 &retValue) {
  unsigned __int64 c, n = 0, overflow = 0;
  int digits_found = 0;
  const char *limit = from + len;
  while (from < limit)
  {
    c = *from;
    if (!isxdigit(c))
      break;
    from++;
    overflow |= n ^ (n << 4 >> 4);
    n = (n << 4) + GetHexValue(c);
    digits_found = 1;
  }
  if (!digits_found) 
    return false;
  if (overflow) {
    assert(false);
  }
  retValue = n;
  return true;
}
bool GetOct(const char *&from, size_t len,
            unsigned __int64 &retValue) {
  unsigned __int64 c, n = 0;
  bool overflow = false;
  const char *limit = from + len;
  while (from < limit)
  {
    c = *from;
    if (c < '0' || c > '7')
      break;
    from++;
    overflow |= static_cast<bool>(n ^ (n << 3 >> 3));
    n = (n << 3) + c - '0';
  }
  retValue = n;
  return true;
}
#define HOST_CHARSET_ASCII
bool GetEscape(const char *from, size_t len,
               unsigned __int64 &retValue) {
  /* Values of \a \b \e \f \n \r \t \v respectively.  */
    // HOST_CHARSET_ASCII
    static const char charconsts[] =
      {  7,  8, 27, 12, 10, 13,  9, 11 };
    // HOST_CHARSET_EBCDIC
    //static const uchar charconsts[] =
      { 47, 22, 39, 12, 21, 13,  5, 11 };
  unsigned char c;
  c = from[0];
  switch (c)
  {
    /* UCNs, hex escapes, and octal escapes
       are processed separately.  */
  case 'u': case 'U': 
    // convert_ucn - not supported. Return: 65535.
    retValue = 0xFFFFui64;
    return true;
  case 'x': {
    const char *p = from + 1;
    return GetHex(p, len, retValue);
  }
  case '0':  case '1':  case '2':  case '3':
  case '4':  case '5':  case '6':  case '7': {
    const char *p = from + 1;
    return GetOct(p, len, retValue);
  }
  
  case '\\': case '\'': case '"': case '?':
    break;
  case 'a': c = charconsts[0]; break;
  case 'b': c = charconsts[1];  break;
  case 'f': c = charconsts[3];  break;
  case 'n': c = charconsts[4];  break;
  case 'r': c = charconsts[5];  break;
  case 't': c = charconsts[6];  break;
  case 'v': c = charconsts[7];  break;
  case 'e': case 'E': c = charconsts[2]; break;
  default:
    assert(false);
    return false;
  }
  retValue = c;
  return true;
}
//'A', '\t', L'A', '\xFE'
static bool GetCharLiteral(const char *from,
                           size_t len,
                           unsigned __int64 &retValue) {
  if (len >= 3) {
    if (from[0] == '\'' && from[len - 1] == '\'') {
      unsigned char c = from[1];
      if (c == '\\') {
        verify(GetEscape(from + 2, len - 3, retValue));
      } else {
        retValue = c;
      }
      return true;
    }
  }
  if (len >= 4) {
    if (from[0] == 'L' &&
        from[1] == '\'' &&
        from[len - 1] == '\'') {
      unsigned char c = from[2];
      if (c == '\\') {
        verify(GetEscape(from + 3, len - 4, retValue));
      } else {
        retValue = c;
      }
      return true;
    }
  }
  return false;
}
// "string"
static bool GetStringLiteral(const char *from, size_t len) {
  if (len >= 2) {
    if (from[0] == '"' && from[len - 1] == '"')
      return true;
  }
  if (len >= 3) {
    if (from[0] == 'L' &&
        from[1] == '"' &&
        from[len - 1] == '"')
      return true;
  }
  return false;
}
bool IsRealLiteral(const char *from, size_t len) {
  if (len < 2)
    return false;
  bool isReal = false;
  bool digitFound = false;
  for (size_t i = 0; i != len; ++i) {
    unsigned char c = from[i];
    switch(c) {
      case 'x': return false;
      case 'X': return false;
      case 'f': isReal = true; break;
      case 'F': isReal = true; break;
      case '.': isReal = true; break;
      case 'e': isReal = true; break;
      case 'E': isReal = true; break;
      case 'l': break;
      case '-': break;
      case '+': break;
      case 'L': break;
      default:
        if (!isdigit(c))
          return false;
        digitFound = true;
    }
  }
  return isReal && digitFound;
}
SimpleType GetRealLiteral(const char *from, size_t len) {
  assert(len > 1);
  unsigned char rc1 = from[len - 1];
  if (is_digit(rc1) || rc1 == '.' ||
      rc1 == 'l' || rc1 == 'L' ||
      rc1 == 'e' || rc1 == 'E')
    return ST_DOUBLE;
  if (rc1 == 'f' || rc1 == 'F')
    return ST_FLOAT;
  assert(false);
  return ST_UNKNOWN;
}
bool GetBoolLiteral(const char *from, size_t len,
                    unsigned __int64 &retValue) {
  if (len == 4 && strncmp(from, "true", 4) == 0) {
    retValue = 1;
    return true;
  }
  if (len == 5 && strncmp(from, "false", 5) == 0) {
    retValue = 0;
    return true;
  }
  return false;
}
bool IsHexLiteral(const char *from, size_t len) {
  if (len < 3)
    return false;
  if (from[0] != '0')
    return false;
  if (from[1] != 'x' && from[1] != 'X')
    return false;
  return true;
}
SimpleType GetTypeBySufix(const char *from, size_t len) {
  assert(from != NULL);
  if (len == 0)
    return ST_INT;
  assert(!isdigit(*from));
  bool suffix_8 = false;
  bool suffix_16 = false;
  bool suffix_32 = false;
  bool suffix_64 = false;
  bool suffix_i = false;
  bool suffix_l = false;
  bool suffix_u = false;
  while (len != 0) {
    --len;
    const char c = *from++;
    switch(c) {
      case '8': suffix_8 = true; break;
      case '1': 
        if (len == 0 || *from++ != '6') {
          assert(false);
          return ST_UNKNOWN;
        }
        --len;
        suffix_16 = true;
        break;
      case '3':
        if (len == 0 || *from++ != '2') {
          assert(false);
          return ST_UNKNOWN;
        }
        --len;
        suffix_32 = true;
        break;
      case '6':
        if (len == 0 || *from++ != '4') {
          assert(false);
          return ST_UNKNOWN;
        }
        --len;
        suffix_64 = true;
        break;
      case 'I':
      case 'i': suffix_i = true; break;
      case 'U':
      case 'u': suffix_u = true; break;
      case 'L':
      case 'l': suffix_l = true; break;
      default:
        assert(false);
        return ST_UNKNOWN;
    }
  }
  assert(suffix_8 + suffix_16 + suffix_32 + suffix_64 <= 1);
  
  if (suffix_8 || suffix_16)
    return ST_LESS_INT;
  
  if (suffix_32) {
    if (suffix_u)
      return ST_UINT;
    else
      return ST_INT;
  }
  if (suffix_64) {
    if (suffix_u)
      return ST_UINT64;
    else
      return ST_INT64;
  }
  if (suffix_l) {
    if (suffix_u)
      return ST_ULONG;
    else
      return ST_LONG;
  }
  if (suffix_u)
    return ST_UINT;
  assert(suffix_i);
  return ST_INT;
}
SimpleType GetHexLiteral(const char *from, size_t len,
                         unsigned __int64 &retValue) {
  assert(len >= 3);
  const char *p = from + 2;
  if (!GetHex(p, len, retValue)) {
    return ST_UNKNOWN;
  }
  ptrdiff_t newLen = len - (p - from);
  assert(newLen >= 0 && newLen < static_cast<ptrdiff_t>(len));
  return GetTypeBySufix(p, newLen);
}
bool IsOctLiteral(const char *from, size_t len) {
  if (len < 2)
    return false;
  if (from[0] != '0')
    return false;
  return true;
}
SimpleType GetOctLiteral(const char *from, size_t len,
                         unsigned __int64 &retValue) {
  assert(len >= 2);
  const char *p = from + 1;
  if (!GetOct(p, len, retValue)) {
    return ST_UNKNOWN;
  }
  ptrdiff_t newLen = len - (p - from);
  assert(newLen >= 0 && newLen < static_cast<ptrdiff_t>(len));
  return GetTypeBySufix(p, newLen);
}
SimpleType GetDecLiteral(const char *from, size_t len,
                         unsigned __int64 &retValue) {
  assert(len >= 1);
  const char *limit = from + len;
  unsigned __int64 n = 0;
  while (from < limit) {
    const char c = *from;
    if (c < '0' || c > '9')
      break;
    from++;
    n = n * 10 + (c - '0');
  }
  ptrdiff_t newLen = limit - from;
  if (newLen == static_cast<ptrdiff_t>(len))
    return ST_UNKNOWN;
  retValue = n;
  assert(newLen >= 0 && newLen < static_cast<ptrdiff_t>(len));
  return GetTypeBySufix(from, newLen);
}
SimpleType GetLiteralType(const char *from, size_t len,
                          unsigned __int64 &retValue) {
  if (from == NULL || len == 0)
    return ST_UNKNOWN;
  retValue = 1;
  if (from == NULL || len == 0)
    return ST_UNKNOWN;
  if (GetCharLiteral(from, len, retValue))
    return ST_LESS_INT;
  if (GetStringLiteral(from, len))
    return ST_POINTER;
  if (GetBoolLiteral(from, len, retValue))
    return ST_LESS_INT;
  if (IsRealLiteral(from, len))
    return GetRealLiteral(from, len);
  if (IsHexLiteral(from, len))
    return GetHexLiteral(from, len, retValue);
  if (IsOctLiteral(from, len))
    return GetOctLiteral(from, len, retValue);
  return GetDecLiteral(from, len, retValue);
}

Comments

  1. 01 Jan 1999 at 00:00

Leave a comment

Sign in or Join us (it's free).

AddThis

Related discussion

Events coming up

  • Dec 6

    Developing AJAX Web Applications with Castle Monorail

    London, United Kingdom

    Monorail is the model-view-controller engine of the Castle Project, bringing many of the best ideas of Ruby on Rails to the .NET world. In this talk, David De Florinier and Gojko Adzic show how Monorail makes it easy to develop .NET based AJAX applications, and how to use the Castle Project to build Web 2.0 applications effectively. Come to this session if you are a .NET web developer. Everyone is welcome!