Library tutorials & articles
The use of the code analysis library OpenC++: modifications, improvements, error corrections
- Annotation
- Introduction.
- 1. Skip of development environment keywords not influencing the program processing
- 2. Addition of a new lexeme.
- 3. Skip of development environment complex key constructions not influencing the program processing.
- 4. Function of full file paths disclosure.
- 5. Getting values of numerical literals.
- 6. Correction of string literal processing function.
- 7. Partial correction of the processing of "bool r = a < 1 || b > (int) 2;" type expressions.
- 8. Improved error correction.
- 9. Update of rTemplateDecl2 function.
- 10. Detection of Ptree position in the program text.
- 11. Support of const A (a) type definitions.
- 12. Support of definitions in classes of T (min)() { } type functions.
- 13. Processing of constructions "using" and "namespace" inside functions.
- 14. Making “this” a pointer.
- 15. Optimization of LineNumber() function.
- 16. Correction of the error occurring while analyzing "#line" directive.
- Conclusion.
- Resources.
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);
}
|
Related articles
Related discussion
-
conting repeated words
by Slicksim (2 replies)
-
Can somebody help: CAsyncSOcket class (Client-server networking)
by Mohammad Rastkar (3 replies)
-
custom progress bar in a datagridview with threading
by konikula (1 replies)
-
Calling C++ DLL from C#
by Thushan Fernando (1 replies)
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!
This thread is for discussions of The use of the code analysis library OpenC++: modifications, improvements, error corrections.