cprover
format_strings.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Format String Parser
4 
5 Author: CM Wintersteiger
6 
7 \*******************************************************************/
8 
11 
12 #include "format_strings.h"
13 
14 #include <util/std_types.h>
15 #include <util/std_expr.h>
16 
17 #include <util/c_types.h>
18 
19 #include <cctype>
20 
22  std::string::const_iterator &it,
23  format_tokent &curtok)
24 {
25  while(*it=='#' || *it=='0' ||
26  *it=='-' || *it==' ' || *it=='+')
27  {
28  switch(*it)
29  {
30  case '#':
31  curtok.flags.push_back(format_tokent::flag_typet::ALTERNATE); break;
32  case '0':
33  curtok.flags.push_back(format_tokent::flag_typet::ZERO_PAD); break;
34  case '-':
35  curtok.flags.push_back(format_tokent::flag_typet::LEFT_ADJUST); break;
36  case ' ':
37  curtok.flags.push_back(format_tokent::flag_typet::SIGNED_SPACE); break;
38  case '+':
39  curtok.flags.push_back(format_tokent::flag_typet::SIGN); break;
40  default: throw 0;
41  }
42  it++;
43  }
44 }
45 
47  std::string::const_iterator &it,
48  format_tokent &curtok)
49 {
50  if(*it=='*')
51  {
53  it++;
54  }
55 
56  std::string tmp;
57  for( ; isdigit(*it); it++) tmp+=*it;
58  curtok.field_width=string2integer(tmp);
59 }
60 
62  std::string::const_iterator &it,
63  format_tokent &curtok)
64 {
65  if(*it=='.')
66  {
67  it++;
68 
69  if(*it=='*')
70  {
72  it++;
73  }
74  else
75  {
76  std::string tmp;
77  for( ; isdigit(*it); it++) tmp+=*it;
78  curtok.precision=string2integer(tmp);
79  }
80  }
81 }
82 
84  std::string::const_iterator &it,
85  format_tokent &curtok)
86 {
87  if(*it=='h')
88  {
89  it++;
90  if(*it=='h')
91  it++;
93  }
94  else if(*it=='l')
95  {
96  it++;
97  if(*it=='l')
98  it++;
100  }
101  else if(*it=='L')
102  {
103  it++;
105  }
106  else if(*it=='j')
107  {
108  it++;
110  }
111  else if(*it=='t')
112  {
113  it++;
115  }
116 }
117 
119  const std::string &arg_string,
120  std::string::const_iterator &it,
121  format_tokent &curtok)
122 {
123  switch(*it)
124  {
125  case 'd':
126  case 'i':
129  break;
130  case 'o':
133  break;
134  case 'u':
137  break;
138  case 'x':
139  case 'X':
142  break;
143  case 'e':
144  case 'E': curtok.type=format_tokent::token_typet::FLOAT; break;
145  case 'f':
146  case 'F': curtok.type=format_tokent::token_typet::FLOAT; break;
147  case 'g':
148  case 'G': curtok.type=format_tokent::token_typet::FLOAT; break;
149  case 'a':
150  case 'A': curtok.type=format_tokent::token_typet::FLOAT; break;
151  case 'c': curtok.type=format_tokent::token_typet::CHAR; break;
152  case 's': curtok.type=format_tokent::token_typet::STRING; break;
153  case 'p': curtok.type=format_tokent::token_typet::POINTER; break;
154  case '%':
156  curtok.value="%";
157  break;
158  case '[': // pattern matching in, e.g., fscanf.
159  {
160  std::string tmp;
161  it++;
162  if(*it=='^') // if it's there, it must be first
163  {
164  tmp+='^'; it++;
165  if(*it==']') // if it's there, it must be here
166  {
167  tmp+=']'; it++;
168  }
169  }
170 
171  for( ; it!=arg_string.end() && *it!=']'; it++)
172  tmp+=*it;
173 
174  break;
175  }
176 
177  default:
178  throw std::string("unsupported format conversion specifier: `")+*it+"'";
179  }
180  it++;
181 }
182 
183 format_token_listt parse_format_string(const std::string &arg_string)
184 {
185  format_token_listt token_list;
186 
187  std::string::const_iterator it=arg_string.begin();
188 
189  while(it!=arg_string.end())
190  {
191  if(*it=='%')
192  {
193  token_list.push_back(format_tokent());
194  format_tokent &curtok=token_list.back();
195  it++;
196 
197  parse_flags(it, curtok);
198  parse_field_width(it, curtok);
199  parse_precision(it, curtok);
200  parse_length_modifier(it, curtok);
201  parse_conversion_specifier(arg_string, it, curtok);
202  }
203  else
204  {
205  if(token_list.empty() ||
206  token_list.back().type!=format_tokent::token_typet::TEXT)
207  token_list.push_back(format_tokent(format_tokent::token_typet::TEXT));
208 
209  std::string tmp;
210  for( ; it!=arg_string.end() && *it!='%'; it++)
211  tmp+=*it;
212 
213  assert(!token_list.empty());
214  token_list.back().value=tmp;
215  }
216  }
217 
218  return token_list;
219 }
220 
222 {
223  switch(token.type)
224  {
226  switch(token.length_modifier)
227  {
230  return signed_char_type();
231  else
232  return unsigned_char_type();
233 
236  return signed_short_int_type();
237  else
238  return unsigned_short_int_type();
239 
242  return signed_long_int_type();
243  else
244  return unsigned_long_int_type();
245 
248  return signed_long_long_int_type();
249  else
251 
252  default:
254  return signed_int_type();
255  else
256  return unsigned_int_type();
257  }
258 
260  switch(token.length_modifier)
261  {
264  default: return float_type();
265  }
266 
268  switch(token.length_modifier)
269  {
271  default: return char_type();
272  }
273 
275  return pointer_type(void_type());
276 
278  switch(token.length_modifier)
279  {
281  return array_typet(wchar_t_type(), nil_exprt());
282  default: return array_typet(char_type(), nil_exprt());
283  }
284 
285  default:
286  return nil_typet();
287  }
288 }
The type of an expression.
Definition: type.h:20
typet void_type()
Definition: c_types.cpp:306
pointer_typet pointer_type(const typet &subtype)
Definition: c_types.cpp:296
const mp_integer string2integer(const std::string &n, unsigned base)
Definition: mp_arith.cpp:53
format_token_listt parse_format_string(const std::string &arg_string)
unsignedbv_typet unsigned_int_type()
Definition: c_types.cpp:43
irep_idt value
Format String Parser.
bitvector_typet double_type()
Definition: c_types.cpp:203
mp_integer precision
typet get_type(const format_tokent &token)
length_modifierst length_modifier
bitvector_typet float_type()
Definition: c_types.cpp:184
The NIL expression.
Definition: std_expr.h:3764
API to expression classes.
void parse_precision(std::string::const_iterator &it, format_tokent &curtok)
signedbv_typet signed_long_int_type()
Definition: c_types.cpp:79
void parse_length_modifier(std::string::const_iterator &it, format_tokent &curtok)
token_typet type
bitvector_typet long_double_type()
Definition: c_types.cpp:222
signedbv_typet signed_short_int_type()
Definition: c_types.cpp:36
bitvector_typet wchar_t_type()
Definition: c_types.cpp:148
API to type classes.
std::list< flag_typet > flags
unsignedbv_typet unsigned_short_int_type()
Definition: c_types.cpp:50
mp_integer field_width
The NIL type.
Definition: std_types.h:43
void parse_flags(std::string::const_iterator &it, format_tokent &curtok)
unsignedbv_typet unsigned_long_long_int_type()
Definition: c_types.cpp:100
arrays with given size
Definition: std_types.h:901
signedbv_typet signed_int_type()
Definition: c_types.cpp:29
representationt representation
unsignedbv_typet unsigned_char_type()
Definition: c_types.cpp:134
unsignedbv_typet unsigned_long_int_type()
Definition: c_types.cpp:93
signedbv_typet signed_long_long_int_type()
Definition: c_types.cpp:86
void parse_field_width(std::string::const_iterator &it, format_tokent &curtok)
signedbv_typet signed_char_type()
Definition: c_types.cpp:141
bitvector_typet char_type()
Definition: c_types.cpp:113
void parse_conversion_specifier(const std::string &arg_string, std::string::const_iterator &it, format_tokent &curtok)