<commit_before>// -*- mode: C++ -*-
//
// Copyright (c) 2007, 2008, 2009, 2010, 2011 The University of Utah
// All rights reserved.
//
// This file is part of `csmith', a random generator of C programs.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in the
//     documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "Constant.h"
#include <cassert>
#include <ostream>
#include <string>
#include <iostream>
#include <sstream>
#include <cmath>
#include <climits>

#include "CGContext.h"
#include "Type.h"
#include "Variable.h"
#include "Error.h"
#include "CGOptions.h"
#include "StringUtils.h"
#include "random.h"

using namespace std;

static string GenerateRandomConstant(const Type* type);

///////////////////////////////////////////////////////////////////////////////

/*
 * TODO: make well-known constants
 */

///////////////////////////////////////////////////////////////////////////////

/*
 * 
 */
Constant::Constant(const Type *t, const string &v)
	: Expression(eConstant),
	  type(t),
	  value(v)
{
}

/*
 * 
 */
Constant::Constant(const Constant &c)
	: Expression(eConstant),
	  type(c.type),
	  value(c.value)
{
}

/*
 * 
 */
Constant::~Constant(void)
{
	// Nothing else to do.
}

///////////////////////////////////////////////////////////////////////////////

Expression *
Constant::clone() const
{
	return new Constant(*this);
}

// --------------------------------------------------------------
static string
GenerateRandomCharConstant(void)
{
	string ch;
	if (CGOptions::ccomp())
		ch = string("0x") + RandomHexDigits(2);
	else
		ch = string("0x") + RandomHexDigits(2) + "L";
	return ch;
}

// --------------------------------------------------------------
static string
GenerateRandomIntConstant(void)
{
	string val;
	// Int constant - Max 8 Hex digits on 32-bit platforms
	if (CGOptions::ccomp())
		val = "0x" + RandomHexDigits( 8 );
	else
		val = "0x" + RandomHexDigits( 8 ) + "L";
	
	return val;
}

// --------------------------------------------------------------
static string
GenerateRandomShortConstant(void)
{
	string val;
	// Short constant - Max 4 Hex digits on 32-bit platforms
	if (CGOptions::ccomp())
		val = "0x" + RandomHexDigits( 4 );
	else
		val = "0x" + RandomHexDigits( 4 ) + "L";

	return val;
}

// --------------------------------------------------------------
static string
GenerateRandomLongConstant(void)
{
	// Long constant - Max 8 Hex digits on 32-bit platforms
	string val = "0x" + RandomHexDigits( 8 ) + "L";
	return val;
}

// --------------------------------------------------------------
static string
GenerateRandomLongLongConstant(void)
{
	// Long constant - Max 8 Hex digits on 32-bit platforms
	string val = "0x" + RandomHexDigits( 16 ) + "L";
	return val;
}

// --------------------------------------------------------------
#if 0
static string
GenerateRandomFloatConstant(void)
{
	// Generate a random floating point value with up to 10 digits of precision. (should look up precision of float/double.. 23 bits for IEEE-32?)
	string val = RandomDigits(5) + "." + RandomDigits(5);
	return val;
}
#endif // 0

static string
GenerateRandomConstantInRange(const Type* type, int bound)
{
	assert(type->eType == eSimple);

	ostringstream oss;
	if (type->simple_type == eInt) {
		int b = static_cast<int>(pow(2, static_cast<double>(bound) / 2));
		int num = pure_rnd_upto(b);
		ERROR_GUARD("");
		bool flag = pure_rnd_flipcoin(50);
		ERROR_GUARD("");
		if (flag)
			oss << num;
		else 
			oss << "-" << num;
	}
	else if (type->simple_type == eUInt) {
		int b = static_cast<int>(pow(2, static_cast<double>(bound) / 2));
		if (b < 0)
			b = INT_MAX;
		int num = pure_rnd_upto(b);
		ERROR_GUARD("");
		oss << num;
	}
	else {
		assert(0);
	}
	return CGOptions::mark_mutable_const() ? "(" + oss.str() + ")" : oss.str();
}

// --------------------------------------------------------------
  /* generate a constant struct in the form of 
   * "{2, 4, {2, 4}, 6.0}"
   *************************************************************/
static string
GenerateRandomStructConstant(const Type* type)
{ 
	string value = "{";
	size_t i;
	assert(type->eType == eStruct);
	assert(type->fields.size() == type->bitfields_length_.size());

	for (i = 0; i < type->fields.size(); i++) {
		bool is_bitfield = type->is_bitfield(i);
		if (is_bitfield) {
			int bound = type->bitfields_length_[i];
			if (bound == 0)
				continue;
			string v = GenerateRandomConstantInRange(type->fields[i], bound);
			ERROR_GUARD("");
			if (i > 0) {
				value += ",";
			}
			value += v;
		}
		else {
        		string v = GenerateRandomConstant(type->fields[i]);
			ERROR_GUARD("");
        		if (i > 0) {
            			value += ",";
			}
        		value += v;
		}
	}
	value += "}"; 
	return value;
}

// --------------------------------------------------------------
  /* generate an union initializer: unlike struct, initializing
     the first field is enough 
   *************************************************************/
static string
GenerateRandomUnionConstant(const Type* type)
{ 
	string value = "{"; 
	assert(type->eType == eUnion && type->fields.size() == type->bitfields_length_.size());
	value += GenerateRandomConstant(type->fields[0]);
	value += "}"; 
	return value;
}

static string
GenerateRandomConstant(const Type* type)
{
    string v;
	if (type == 0) {
		v = "0";
	}
    else if (type->eType == eStruct) {
        v = GenerateRandomStructConstant(type);
		ERROR_GUARD("");
    }
	else if (type->eType == eUnion) {
        v = GenerateRandomUnionConstant(type);
		ERROR_GUARD("");
    }
    // the only possible constant for a pointer is "0"
    else if (type->eType == ePointer) {
        v = "0";
    }
    else if (type->eType == eSimple) {
        eSimpleType st = type->simple_type;
	    assert(st != eVoid);
	    //assert((eType >= 0) && (eType <= MAX_SIMPLE_TYPES)); 
	    if (pure_rnd_flipcoin(50)) {
		    ERROR_GUARD("");
		    int num = 0;
		    if (pure_rnd_flipcoin(50)) {
			    ERROR_GUARD("");
			    num = pure_rnd_upto(3)-1;
		    } else {
			    ERROR_GUARD("");
			    num = pure_rnd_upto(20)-10;
		    }
			// don't use negative number for unsigned type, as this causes 
			//trouble for some static analyzers  
		    ostringstream oss; 
			switch (type->simple_type) {
				case eUChar:     oss << (unsigned int)(unsigned char)num;		break;
				case eUShort:    oss << (unsigned short)num;	break;
				case eUInt:
				case eULong:     oss << (unsigned int)num;		break;
				case eULongLong:  
					if (!CGOptions::longlong()) {
						oss << (unsigned int)num;
					} else { 
						oss << ((type->simple_type == eULong) ? (unsigned long)num : (unsigned INT64)num);
					}
					break; 
				default:		 oss << num; break;
			} 
			if (CGOptions::ccomp())
				v = oss.str() + (type->is_signed() ? "" : "U");
			else
				v = oss.str() + (type->is_signed() ? "L" : "UL");
	    } else {
		    switch (st) {
		    case eVoid:      v = "/* void */";						break;
		    case eChar:      v = GenerateRandomCharConstant();		break;
		    case eInt:       v = GenerateRandomIntConstant();		break;
		    case eShort:     v = GenerateRandomShortConstant();		break;
		    case eLong:      v = GenerateRandomLongConstant();		break;
	        case eLongLong:  v = GenerateRandomLongLongConstant();	break;
		    case eUChar:     v = GenerateRandomCharConstant();		break;
		    case eUInt:      v = GenerateRandomIntConstant();		break;
		    case eUShort:    v = GenerateRandomShortConstant();		break;
		    case eULong:     v = GenerateRandomLongConstant();		break;
	        case eULongLong: v = GenerateRandomLongLongConstant();	break;
    //	    case eFloat:     v = GenerateRandomFloatConstant();		break;
    //	    case eDouble:    v = GenerateRandomFloatConstant();		break;
		    }
        }
    } else {
        assert(0);  // no support for types other than integers and structs for now
    }
	return (type->eType == eSimple && CGOptions::mark_mutable_const()) ? "(" + v + ")" : v;<commit_msg>Fix producing out-of-bounds hex constants. Also cleanup.<commit_after>// -*- mode: C++ -*-
//
// Copyright (c) 2007, 2008, 2009, 2010, 2011 The University of Utah
// All rights reserved.
//
// This file is part of `csmith', a random generator of C programs.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in the
//     documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "Constant.h"
#include <cassert>
#include <ostream>
#include <string>
#include <iostream>
#include <sstream>
#include <cmath>
#include <climits>
#include <cctype>

#include "CGContext.h"
#include "Type.h"
#include "Variable.h"
#include "Error.h"
#include "CGOptions.h"
#include "StringUtils.h"
#include "random.h"

using namespace std;

static string GenerateRandomConstant(const Type* type);

///////////////////////////////////////////////////////////////////////////////

/*
 * TODO: make well-known constants
 */

///////////////////////////////////////////////////////////////////////////////

/*
 * 
 */
Constant::Constant(const Type *t, const string &v)
	: Expression(eConstant),
	  type(t),
	  value(v)
{
}

/*
 * 
 */
Constant::Constant(const Constant &c)
	: Expression(eConstant),
	  type(c.type),
	  value(c.value)
{
}

/*
 * 
 */
Constant::~Constant(void)
{
	// Nothing else to do.
}

///////////////////////////////////////////////////////////////////////////////

Expression *
Constant::clone() const
{
	return new Constant(*this);
}

// --------------------------------------------------------------
static void
PutRandomSignedConstantInRange(string *ch) {
	int first_digit = StringUtils::str2int(ch->substr(0, 3));
	if (first_digit >= 8)
		(*ch)[2] = '0' + (first_digit - 8);
}

// --------------------------------------------------------------
static string
GenerateRandomCharConstant(void)
{
	string ch;
	if (CGOptions::ccomp())
		ch = string("0x") + RandomHexDigits(2);
	else
		ch = string("0x") + RandomHexDigits(2) + "L";
	return ch;
}

// --------------------------------------------------------------
static string
GenerateRandomIntConstant(void)
{
	string val;
	// Int constant - Max 8 Hex digits on 32-bit platforms
	if (CGOptions::ccomp())
		val = "0x" + RandomHexDigits( 8 );
	else
		val = "0x" + RandomHexDigits( 8 ) + "L";
	
	return val;
}

// --------------------------------------------------------------
static string
GenerateRandomShortConstant(void)
{
	string val;
	// Short constant - Max 4 Hex digits on 32-bit platforms
	if (CGOptions::ccomp())
		val = "0x" + RandomHexDigits( 4 );
	else
		val = "0x" + RandomHexDigits( 4 ) + "L";

	return val;
}

// --------------------------------------------------------------
static string
GenerateRandomLongConstant(void)
{
	// Long constant - Max 8 Hex digits on 32-bit platforms
	string val = "0x" + RandomHexDigits( 8 ) + "L";
	return val;
}

// --------------------------------------------------------------
static string
GenerateRandomLongLongConstant(void)
{
	// Long constant - Max 8 Hex digits on 32-bit platforms
	string val = "0x" + RandomHexDigits( 16 ) + "L";
	return val;
}

// --------------------------------------------------------------
#if 0
static string
GenerateRandomFloatConstant(void)
{
	// Generate a random floating point value with up to 10 digits of precision. (should look up precision of float/double.. 23 bits for IEEE-32?)
	string val = RandomDigits(5) + "." + RandomDigits(5);
	return val;
}
#endif // 0

static string
GenerateRandomConstantInRange(const Type* type, int bound)
{
	assert(type->eType == eSimple);

	ostringstream oss;
	if (type->simple_type == eInt) {
		int b = static_cast<int>(pow(2, static_cast<double>(bound) / 2));
		int num = pure_rnd_upto(b);
		ERROR_GUARD("");
		bool flag = pure_rnd_flipcoin(50);
		ERROR_GUARD("");
		if (flag)
			oss << num;
		else 
			oss << "-" << num;
	}
	else if (type->simple_type == eUInt) {
		int b = static_cast<int>(pow(2, static_cast<double>(bound) / 2));
		if (b < 0)
			b = INT_MAX;
		int num = pure_rnd_upto(b);
		ERROR_GUARD("");
		oss << num;
	}
	else {
		assert(0);
	}
	return CGOptions::mark_mutable_const() ? "(" + oss.str() + ")" : oss.str();
}

// --------------------------------------------------------------
  /* generate a constant struct in the form of 
   * "{2, 4, {2, 4}, 6.0}"
   *************************************************************/
static string
GenerateRandomStructConstant(const Type* type)
{ 
	string value = "{";
	size_t i;
	assert(type->eType == eStruct);
	assert(type->fields.size() == type->bitfields_length_.size());

	for (i = 0; i < type->fields.size(); i++) {
		bool is_bitfield = type->is_bitfield(i);
		if (is_bitfield) {
			int bound = type->bitfields_length_[i];
			if (bound == 0)
				continue;
			string v = GenerateRandomConstantInRange(type->fields[i], bound);
			ERROR_GUARD("");
			if (i > 0) {
				value += ",";
			}
			value += v;
		}
		else {
        		string v = GenerateRandomConstant(type->fields[i]);
			ERROR_GUARD("");
        		if (i > 0) {
            			value += ",";
			}
        		value += v;
		}
	}
	value += "}"; 
	return value;
}

// --------------------------------------------------------------
  /* generate an union initializer: unlike struct, initializing
     the first field is enough 
   *************************************************************/
static string
GenerateRandomUnionConstant(const Type* type)
{ 
	string value = "{"; 
	assert(type->eType == eUnion && type->fields.size() == type->bitfields_length_.size());
	value += GenerateRandomConstant(type->fields[0]);
	value += "}"; 
	return value;
}

static string
GenerateRandomConstant(const Type* type)
{
    string v;
	if (type == 0) {
		v = "0";
	}
    else if (type->eType == eStruct) {
        v = GenerateRandomStructConstant(type);
		ERROR_GUARD("");
    }
	else if (type->eType == eUnion) {
        v = GenerateRandomUnionConstant(type);
		ERROR_GUARD("");
    }
    // the only possible constant for a pointer is "0"
    else if (type->eType == ePointer) {
        v = "0";
    }
    else if (type->eType == eSimple) {
        eSimpleType st = type->simple_type;
	    assert(st != eVoid);
	    //assert((eType >= 0) && (eType <= MAX_SIMPLE_TYPES)); 
	    if (pure_rnd_flipcoin(50)) {
		    ERROR_GUARD("");
		    int num = 0;
		    if (pure_rnd_flipcoin(50)) {
			    ERROR_GUARD("");
			    num = pure_rnd_upto(3)-1;
		    } else {
			    ERROR_GUARD("");
			    num = pure_rnd_upto(20)-10;
		    }
			// don't use negative number for unsigned type, as this causes 
			//trouble for some static analyzers  
		    ostringstream oss; 
			switch (type->simple_type) {
				case eUChar:     oss << (unsigned int)(unsigned char)num;		break;
				case eUShort:    oss << (unsigned short)num;	break;
				case eUInt:
				case eULong:     oss << (unsigned int)num;		break;
				case eULongLong:  
					if (!CGOptions::longlong()) {
						oss << (unsigned int)num;
					} else { 
						oss << ((type->simple_type == eULong) ? (unsigned long)num : (unsigned INT64)num);
					}
					break; 
				default:		 oss << num; break;
			} 
			if (CGOptions::ccomp())
				v = oss.str() + (type->is_signed() ? "" : "U");
			else
				v = oss.str() + (type->is_signed() ? "L" : "UL");
		} else {
			switch (st) {
			case eVoid:      v = "/* void */";			break;
			case eChar:      v = GenerateRandomCharConstant();	break;
			case eInt:       v = GenerateRandomIntConstant();	break;
			case eShort:     v = GenerateRandomShortConstant();	break;
			case eLong:      v = GenerateRandomLongConstant();	break;
			case eLongLong:  v = GenerateRandomLongLongConstant();	break;
			case eUChar:     v = GenerateRandomCharConstant();	break;
			case eUInt:      v = GenerateRandomIntConstant();	break;
			case eUShort:    v = GenerateRandomShortConstant();	break;
			case eULong:     v = GenerateRandomLongConstant();	break;
			case eULongLong: v = GenerateRandomLongLongConstant();	break;
			//case eFloat:     v = GenerateRandomFloatConstant();	break;
			//case eDouble:    v = GenerateRandomFloatConstant();	break;
			}
			if (type->is_signed())
				PutRandomSignedConstantInRange(&v);
		}
    } else {
        assert(0);  // no support for types other than integers and structs for now
    }
	return (type->eType == eSimple && CGOptions::mark_mutable_const()) ? "(" + v + ")" : v;
{'fraction_non_alphanumeric': 0.22164781906300485, 'fraction_numerical': 0.010823909531502423, 'mean_word_length': 2.3305236728837877, 'pattern_counts': {'":': 0, '<': 72, '<?xml version=': 0, '>': 85, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5348629', 'n_tokens_mistral': 6214, 'n_tokens_neox': 5533, 'n_words': 1653}