48 #include <iostream> |
48 #include <iostream> |
49 #include <sstream> |
49 #include <sstream> |
50 #include <typeinfo> |
50 #include <typeinfo> |
51 #include <list> |
51 #include <list> |
52 #include <strings.h> |
52 #include <strings.h> |
53 #include <string.h> /* required for strlen() */ |
53 // #include <string.h> /* required for strlen() */ |
54 #include <stdlib.h> /* required for atoi() */ |
54 // #include <stdlib.h> /* required for atoi() */ |
55 #include <errno.h> /* required for errno */ |
55 // #include <errno.h> /* required for errno */ |
56 |
56 |
57 #include "../util/symtable.hh" |
57 #include "../util/symtable.hh" |
58 #include "../util/dsymtable.hh" |
58 #include "../util/dsymtable.hh" |
59 #include "../absyntax/visitor.hh" |
59 #include "../absyntax/visitor.hh" |
|
60 #include "../main.hh" // required for ERROR() and ERROR_MSG() macros. |
60 |
61 |
61 |
62 |
62 |
63 |
63 //#define DEBUG |
64 //#define DEBUG |
64 #ifdef DEBUG |
65 #ifdef DEBUG |
65 #define TRACE(classname) printf("\n____%s____\n",classname); |
66 #define TRACE(classname) printf("\n____%s____\n",classname); |
66 #else |
67 #else |
67 #define TRACE(classname) |
68 #define TRACE(classname) |
68 #endif |
69 #endif |
69 |
70 |
70 #define ERROR error_exit(__FILE__,__LINE__) |
|
71 /* function defined in main.cc */ |
|
72 extern void error_exit(const char *file_name, int line_no); |
|
73 |
71 |
74 |
72 |
75 /***********************************************************************/ |
73 /***********************************************************************/ |
76 /***********************************************************************/ |
74 /***********************************************************************/ |
77 /***********************************************************************/ |
75 /***********************************************************************/ |
92 if (strcasecmp(name1->value, name2->value) == 0) |
90 if (strcasecmp(name1->value, name2->value) == 0) |
93 return 0; |
91 return 0; |
94 |
92 |
95 /* identifiers do not match! */ |
93 /* identifiers do not match! */ |
96 return 1; |
94 return 1; |
97 } |
|
98 |
|
99 |
|
100 |
|
101 /* To allow the compiler to be portable, we cannot assume that int64_t is mapped onto long long int, |
|
102 * so we cannot call strtoll() and strtoull() in extract_int64() and extract_uint64(). |
|
103 * |
|
104 * So, we create our own strtouint64() and strtoint64() functions. |
|
105 * (We actually call them matiec_strtoint64() so they will not clash with any function |
|
106 * that may be added to the standard library in the future). |
|
107 * We actually create several of each, and let the compiler choose which is the correct one, |
|
108 * by having it resolve the call to the overloaded function. For the C++ compiler to be able |
|
109 * to resolve this ambiguity, we need to add a dummy parameter to each function! |
|
110 * |
|
111 * TODO: support platforms in which int64_t is mapped onto int !! Is this really needed? |
|
112 */ |
|
113 static int64_t matiec_strtoint64 ( long int *dummy, const char *nptr, char **endptr, int base) {return strtol (nptr, endptr, base);} |
|
114 static int64_t matiec_strtoint64 ( long long int *dummy, const char *nptr, char **endptr, int base) {return strtoll (nptr, endptr, base);} |
|
115 |
|
116 static uint64_t matiec_strtouint64(unsigned long int *dummy, const char *nptr, char **endptr, int base) {return strtoul (nptr, endptr, base);} |
|
117 static uint64_t matiec_strtouint64(unsigned long long int *dummy, const char *nptr, char **endptr, int base) {return strtoull(nptr, endptr, base);} |
|
118 |
|
119 |
|
120 /* extract the value of an integer from an integer_c object !! */ |
|
121 /* NOTE: it must ignore underscores! */ |
|
122 int64_t extract_int64_value(symbol_c *sym, bool *overflow) { |
|
123 std::string str = ""; |
|
124 integer_c *integer; |
|
125 neg_integer_c * neg_integer; |
|
126 char *endptr; |
|
127 int64_t ret; |
|
128 |
|
129 if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR; |
|
130 for(unsigned int i = 0; i < strlen(integer->value); i++) |
|
131 if (integer->value[i] != '_') str += integer->value[i]; |
|
132 |
|
133 errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! |
|
134 ret = matiec_strtoint64((int64_t *)NULL, str.c_str(), &endptr, 10); |
|
135 if (overflow != NULL) |
|
136 *overflow = (errno == ERANGE); |
|
137 if ((errno != 0) && (errno != ERANGE)) |
|
138 ERROR; |
|
139 |
|
140 return ret; |
|
141 } |
|
142 |
|
143 uint64_t extract_uint64_value(symbol_c *sym, bool *overflow) { |
|
144 std::string str = ""; |
|
145 integer_c *integer; |
|
146 neg_integer_c * neg_integer; |
|
147 char *endptr; |
|
148 uint64_t ret; |
|
149 |
|
150 if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR; |
|
151 for(unsigned int i = 0; i < strlen(integer->value); i++) |
|
152 if (integer->value[i] != '_') str += integer->value[i]; |
|
153 |
|
154 errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! |
|
155 ret = matiec_strtouint64((uint64_t *)NULL, str.c_str(), &endptr, 10); |
|
156 if (overflow != NULL) |
|
157 *overflow = (errno == ERANGE); |
|
158 if ((errno != 0) && (errno != ERANGE)) |
|
159 ERROR; |
|
160 |
|
161 return ret; |
|
162 } |
|
163 |
|
164 |
|
165 /* extract the value of an hex integer from an hex_integer_c object !! */ |
|
166 /* NOTE: it must ignore underscores! */ |
|
167 uint64_t extract_hex_value(symbol_c *sym) { |
|
168 std::string str = ""; |
|
169 char *endptr; |
|
170 hex_integer_c * hex_integer; |
|
171 uint64_t ret; |
|
172 |
|
173 if ((hex_integer = dynamic_cast<hex_integer_c *>(sym)) == NULL) ERROR; |
|
174 for(unsigned int i = 3; i < strlen(hex_integer->value); i++) |
|
175 if (hex_integer->value[i] != '_') str += hex_integer->value[i]; |
|
176 |
|
177 errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! |
|
178 ret = strtoull(str.c_str(), &endptr, 16); |
|
179 if (errno != 0) ERROR; |
|
180 |
|
181 return ret; |
|
182 } |
|
183 |
|
184 |
|
185 /* extract the value of a real from an real_c object !! */ |
|
186 /* NOTE: it must ignore underscores! */ |
|
187 /* From iec_bison.yy |
|
188 * real: |
|
189 * real_token {$$ = new real_c($1, locloc(@$));} |
|
190 * | fixed_point_token {$$ = new real_c($1, locloc(@$));} |
|
191 * |
|
192 * From iec_flex.ll |
|
193 * {real} {yylval.ID=strdup(yytext); return real_token;} |
|
194 * {fixed_point} {yylval.ID=strdup(yytext); return fixed_point_token;} |
|
195 * |
|
196 * real {integer}\.{integer}{exponent} |
|
197 * fixed_point {integer}\.{integer} |
|
198 * exponent [Ee]([+-]?){integer} |
|
199 * integer {digit}((_?{digit})*) |
|
200 */ |
|
201 real64_t extract_real_value(symbol_c *sym, bool *overflow) { |
|
202 std::string str = ""; |
|
203 real_c * real_sym; |
|
204 real64_t ret; |
|
205 |
|
206 if ((real_sym = dynamic_cast<real_c *>(sym)) == NULL) ERROR; |
|
207 for(unsigned int i = 0; i < strlen(real_sym->value); i++) |
|
208 if (real_sym->value[i] != '_') str += real_sym->value[i]; |
|
209 |
|
210 errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! |
|
211 #if (real64_t == float) |
|
212 ret = strtof(str.c_str(), NULL); |
|
213 #elif (real64_t == double) |
|
214 ret = strtod(str.c_str(), NULL); |
|
215 #elif (real64_t == long_double) |
|
216 ret = strtold(str.c_str(), NULL); |
|
217 #else |
|
218 #error Could not determine which data type is being used for real64_t (defined in absyntax.hh). Aborting! |
|
219 #endif |
|
220 if (overflow != NULL) |
|
221 *overflow = (errno == ERANGE); |
|
222 if ((errno != 0) && (errno != ERANGE)) |
|
223 ERROR; |
|
224 |
|
225 return ret; |
|
226 } |
95 } |
227 |
96 |
228 |
97 |
229 |
98 |
230 /***********************************************************************/ |
99 /***********************************************************************/ |