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