1 // -*- mode: C++ -*-
2 //
3 // Copyright (c) 2007, 2008, 2010, 2011, 2015, 2017 The University of Utah
4 // All rights reserved.
5 //
6 // This file is part of `csmith', a random generator of C programs.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions are met:
10 //
11 //   * Redistributions of source code must retain the above copyright notice,
12 //     this list of conditions and the following disclaimer.
13 //
14 //   * Redistributions in binary form must reproduce the above copyright
15 //     notice, this list of conditions and the following disclaimer in the
16 //     documentation and/or other materials provided with the distribution.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 
30 // util.cpp --- various utility functions
31 
32 #if HAVE_CONFIG_H
33 #  include <config.h>
34 #endif
35 
36 #include "util.h"
37 
38 #include <string>
39 #include <iostream>
40 #include <sstream>
41 #include <cassert>
42 #include <vector>
43 #include "OutputMgr.h"
44 #include "AbsProgramGenerator.h"
45 #include "CGOptions.h"
46 
47 using namespace std;
48 ///////////////////////////////////////////////////////////////////////////////
49 
50 static int gensym_count = 0;
51 
52 void
reset_gensym()53 reset_gensym()
54 {
55 	gensym_count = 0;
56 }
57 
58 /*
59  *
60  */
61 string
gensym(const char * basename)62 gensym(const char* basename)
63 {
64 	ostringstream ss; //(basename, ios_base::ate); somehow this yields weird result on windows
65 	ss << basename;
66 	ss << ++gensym_count;
67 	return ss.str();
68 }
69 
70 /*
71  *
72  */
73 string
gensym(const string & basename)74 gensym(const string& basename)
75 {
76 	ostringstream ss; //(basename, ios_base::ate);
77 	ss << basename;
78 	ss << ++gensym_count;
79 	return ss.str();
80 }
81 
82 /*
83  * permute an integer array
84  * return: all possible permutations of input integer array
85  */
permute(intvec in)86 vector<intvec> permute(intvec in)
87 {
88 	vector<intvec> out;
89 	/* basic cases */
90 	if (in.size()==0) return out;
91 	if (in.size() == 1) {
92 		out.push_back(in);
93 		return out;
94 	}
95 	/* extended cases: divide the array into head and tail, permute
96 	   tail, then insert head into all possible positions in tail */
97 	int head = in[0];
98 	intvec tail = in;
99 	tail.erase(tail.begin());
100 	vector<intvec> tails = permute(tail);
101 	size_t i, j;
102 	for (i=0; i<tails.size(); i++) {
103 		intvec one_tail = tails[i];
104 		for (j=0; j<=one_tail.size(); j++) {
105 			intvec tmp = one_tail;
106 			tmp.insert(tmp.begin()+j, head);
107 			out.push_back(tmp);
108 		}
109 	}
110 	return out;
111 }
112 
113 /*
114  * given a multi-dimensional array sizes, expand it into all possible array indices
115  * for example: a (2, 2, 2) array will be expanded into the following array of arrays
116  *     (0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1),
117  *     (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)
118  * return: the size of the expanded array of arrays
119  */
expand_within_ranges(vector<unsigned int> in,vector<intvec> & out)120 int expand_within_ranges(vector<unsigned int> in, vector<intvec>& out)
121 {
122 	int i, j;
123 	int dimension = static_cast<int>(in.size());
124 	intvec limits(dimension);
125 	// figure out the maximum number the remaining indices can represent
126 	// like in decimal, the max for each digit starting from right is 10, 100, 1000...
127 	limits[dimension - 1] = in[dimension - 1];
128 	for (i = dimension - 2; i>=0; i--) {
129 		limits[i] = limits[i+1] * in[i];
130 	}
131 	out.clear();
132 	// limit[0] is the maximum number can be represented by all dimensions combined
133 	for (i=0; i<limits[0]; i++) {
134 		intvec tmp;
135 		int num = i;
136 		// calculate the index for each dimension
137 		for (j=0; j<dimension-1; j++) {
138 			tmp.push_back(num / limits[j+1]);
139 			num = num % limits[j+1];
140 		}
141 		tmp.push_back(num);
142 		out.push_back(tmp);
143 	}
144 	return out.size();
145 }
146 
really_outputln(std::ostream & out)147 void really_outputln(std::ostream &out)
148 {
149 	OutputMgr::really_outputln(out);
150 }
151 
outputln(std::ostream & out)152 void outputln(std::ostream &out)
153 {
154 	OutputMgr *output = AbsProgramGenerator::GetOutputMgr();
155 	assert(output);
156 	output->outputln(out);
157 }
158 
output_print_str(std::ostream & out,std::string str,std::string str_value,int indent)159 void output_print_str(std::ostream& out, std::string str, std::string str_value, int indent)
160 {
161 	output_tab(out, indent);
162 	out << "printf(\"";
163 	out << str;
164 	out << "\"";
165 	if (!str_value.empty()) {
166 		out << ", ";
167 		out << str_value;
168 	}
169 	out << ");";
170 }
171 
output_open_encloser(const char * symbol,std::ostream & out,int & indent)172 void output_open_encloser(const char* symbol, std::ostream &out, int& indent)
173 {
174 	output_tab(out, indent);
175 	out << symbol;
176 	outputln(out);
177 	indent++;
178 }
179 
output_close_encloser(const char * symbol,std::ostream & out,int & indent,bool no_newline)180 void output_close_encloser(const char* symbol, std::ostream &out, int& indent, bool no_newline)
181 {
182 	if (!no_newline) {
183 		outputln(out);
184 	}
185 	indent--;
186 	output_tab(out, indent);
187 	out << symbol;
188 }
189 
output_comment_line(std::ostream & out,const std::string & comment)190 void output_comment_line(std::ostream &out, const std::string &comment)
191 {
192 	OutputMgr *output = AbsProgramGenerator::GetOutputMgr();
193 	assert(output);
194 	output->output_comment_line(out, comment);
195 }
196 
output_tab(std::ostream & out,int indent)197 void output_tab(std::ostream &out, int indent)
198 {
199 	OutputMgr *output = AbsProgramGenerator::GetOutputMgr();
200 	assert(output);
201 	output->output_tab(out, indent);
202 }
203 ///////////////////////////////////////////////////////////////////////////////
204 
205 // Local Variables:
206 // c-basic-offset: 4
207 // tab-width: 4
208 // End:
209 
210 // End of file.
211