213 SET_CVALUE(dtype, symbol, oper GET_CVALUE(dtype, arg)); \ |
220 SET_CVALUE(dtype, symbol, oper GET_CVALUE(dtype, arg)); \ |
214 } |
221 } |
215 |
222 |
216 |
223 |
217 |
224 |
|
225 |
|
226 |
|
227 /***********************************************************************/ |
|
228 /***********************************************************************/ |
|
229 /***********************************************************************/ |
|
230 /*** convert string to numerical value ***/ |
|
231 /***********************************************************************/ |
|
232 /***********************************************************************/ |
|
233 /***********************************************************************/ |
|
234 |
|
235 |
|
236 |
|
237 /* To allow the compiler to be portable, we cannot assume that int64_t is mapped onto long long int, |
|
238 * so we cannot call strtoll() and strtoull() in extract_int64() and extract_uint64(). |
|
239 * |
|
240 * So, we create our own strtouint64() and strtoint64() functions. |
|
241 * (We actually call them matiec_strtoint64() so they will not clash with any function |
|
242 * that may be added to the standard library in the future). |
|
243 * We actually create several of each, and let the compiler choose which is the correct one, |
|
244 * by having it resolve the call to the overloaded function. For the C++ compiler to be able |
|
245 * to resolve this ambiguity, we need to add a dummy parameter to each function! |
|
246 * |
|
247 * TODO: support platforms in which int64_t is mapped onto int !! Is this really needed? |
|
248 */ |
|
249 static int64_t matiec_strtoint64 ( long int *dummy, const char *nptr, char **endptr, int base) {return strtol (nptr, endptr, base);} |
|
250 static int64_t matiec_strtoint64 ( long long int *dummy, const char *nptr, char **endptr, int base) {return strtoll (nptr, endptr, base);} |
|
251 |
|
252 static uint64_t matiec_strtouint64(unsigned long int *dummy, const char *nptr, char **endptr, int base) {return strtoul (nptr, endptr, base);} |
|
253 static uint64_t matiec_strtouint64(unsigned long long int *dummy, const char *nptr, char **endptr, int base) {return strtoull(nptr, endptr, base);} |
|
254 |
|
255 |
|
256 /* extract the value of an integer from an integer_c object !! */ |
|
257 /* NOTE: it must ignore underscores! */ |
|
258 int64_t extract_int64_value(symbol_c *sym, bool *overflow) { |
|
259 std::string str = ""; |
|
260 integer_c *integer; |
|
261 char *endptr; |
|
262 int64_t ret; |
|
263 |
|
264 if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR; |
|
265 for(unsigned int i = 0; i < strlen(integer->value); i++) |
|
266 if (integer->value[i] != '_') str += integer->value[i]; |
|
267 |
|
268 errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! |
|
269 ret = matiec_strtoint64((int64_t *)NULL, str.c_str(), &endptr, 10); |
|
270 if (overflow != NULL) |
|
271 *overflow = (errno == ERANGE); |
|
272 if ((errno != 0) && (errno != ERANGE)) |
|
273 ERROR; |
|
274 |
|
275 return ret; |
|
276 } |
|
277 |
|
278 uint64_t extract_uint64_value(symbol_c *sym, bool *overflow) { |
|
279 std::string str = ""; |
|
280 integer_c *integer; |
|
281 neg_integer_c * neg_integer; |
|
282 char *endptr; |
|
283 uint64_t ret; |
|
284 |
|
285 if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR; |
|
286 for(unsigned int i = 0; i < strlen(integer->value); i++) |
|
287 if (integer->value[i] != '_') str += integer->value[i]; |
|
288 |
|
289 errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! |
|
290 ret = matiec_strtouint64((uint64_t *)NULL, str.c_str(), &endptr, 10); |
|
291 if (overflow != NULL) |
|
292 *overflow = (errno == ERANGE); |
|
293 if ((errno != 0) && (errno != ERANGE)) |
|
294 ERROR; |
|
295 |
|
296 return ret; |
|
297 } |
|
298 |
|
299 |
|
300 |
|
301 /* extract the value of an hex integer from an hex_integer_c object !! */ |
|
302 /* NOTE: it must ignore underscores! */ |
|
303 uint64_t extract_hex_value(symbol_c *sym) { |
|
304 std::string str = ""; |
|
305 char *endptr; |
|
306 hex_integer_c * hex_integer; |
|
307 uint64_t ret; |
|
308 |
|
309 if ((hex_integer = dynamic_cast<hex_integer_c *>(sym)) == NULL) ERROR; |
|
310 for(unsigned int i = 3; i < strlen(hex_integer->value); i++) |
|
311 if (hex_integer->value[i] != '_') str += hex_integer->value[i]; |
|
312 |
|
313 errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! |
|
314 ret = strtoull(str.c_str(), &endptr, 16); |
|
315 if (errno != 0) ERROR; |
|
316 |
|
317 return ret; |
|
318 } |
|
319 |
|
320 |
|
321 /* extract the value of a real from an real_c object !! */ |
|
322 /* NOTE: it must ignore underscores! */ |
|
323 /* From iec_bison.yy |
|
324 * real: |
|
325 * real_token {$$ = new real_c($1, locloc(@$));} |
|
326 * | fixed_point_token {$$ = new real_c($1, locloc(@$));} |
|
327 * |
|
328 * From iec_flex.ll |
|
329 * {real} {yylval.ID=strdup(yytext); return real_token;} |
|
330 * {fixed_point} {yylval.ID=strdup(yytext); return fixed_point_token;} |
|
331 * |
|
332 * real {integer}\.{integer}{exponent} |
|
333 * fixed_point {integer}\.{integer} |
|
334 * exponent [Ee]([+-]?){integer} |
|
335 * integer {digit}((_?{digit})*) |
|
336 */ |
|
337 real64_t extract_real_value(symbol_c *sym, bool *overflow) { |
|
338 std::string str = ""; |
|
339 real_c * real_sym; |
|
340 real64_t ret; |
|
341 |
|
342 if ((real_sym = dynamic_cast<real_c *>(sym)) == NULL) ERROR; |
|
343 for(unsigned int i = 0; i < strlen(real_sym->value); i++) |
|
344 if (real_sym->value[i] != '_') str += real_sym->value[i]; |
|
345 |
|
346 errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! |
|
347 #if (real64_t == float) |
|
348 ret = strtof(str.c_str(), NULL); |
|
349 #elif (real64_t == double) |
|
350 ret = strtod(str.c_str(), NULL); |
|
351 #elif (real64_t == long_double) |
|
352 ret = strtold(str.c_str(), NULL); |
|
353 #else |
|
354 #error Could not determine which data type is being used for real64_t (defined in absyntax.hh). Aborting! |
|
355 #endif |
|
356 if (overflow != NULL) |
|
357 *overflow = (errno == ERANGE); |
|
358 if ((errno != 0) && (errno != ERANGE)) |
|
359 ERROR; |
|
360 |
|
361 return ret; |
|
362 } |
|
363 |
|
364 |
|
365 |
|
366 |
|
367 |
|
368 /***********************************************************************/ |
|
369 /***********************************************************************/ |
|
370 /***********************************************************************/ |
|
371 /*** Functions to check for overflow situation ***/ |
|
372 /***********************************************************************/ |
|
373 /***********************************************************************/ |
|
374 /***********************************************************************/ |
218 |
375 |
219 |
376 |
220 /* NOTE: |
377 /* NOTE: |
221 * Most of the conditions to detect overflows on signed and unsigned integer operations were adapted from |
378 * Most of the conditions to detect overflows on signed and unsigned integer operations were adapted from |
222 * https://www.securecoding.cert.org/confluence/display/seccode/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow?showComments=false |
379 * https://www.securecoding.cert.org/confluence/display/seccode/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow?showComments=false |