- 0 ノート
-
Cpp classify number
目次 |
このページを編集する際は,編集に関する方針に従ってください.
編集
概要
編集
- gcc-4.1.0/libcpp/expr.cにて定義
- 数値型を解析して正しいフラグをたてる
- 整数型か、浮動小数点型か
- 大きさ(バイト数)はどのくらいか
- 虚数なのか
- 複数の規格に対応するためのコードが結構ある
引数
編集
- cpp_reader *pfile
- const cpp_token *token
実装
編集
140 /* Categorize numeric constants according to their field (integer, 141 floating point, or invalid), radix (decimal, octal, hexadecimal), 142 and type suffixes. */ 143 unsigned int 144 cpp_classify_number (cpp_reader *pfile, const cpp_token *token) 145 { 146 const uchar *str = token->val.str.text; 147 const uchar *limit; 148 unsigned int max_digit, result, radix; 149 enum {NOT_FLOAT = 0, AFTER_POINT, AFTER_EXPON} float_flag; 150
- 一桁だけならば簡単に分かる
151 /* If the lexer has done its job, length one can only be a single 152 digit. Fast-path this very common case. */ 153 if (token->val.str.len == 1) 154 return CPP_N_INTEGER | CPP_N_SMALL | CPP_N_DECIMAL; 155
- 初期値
156 limit = str + token->val.str.len; 157 float_flag = NOT_FLOAT; 158 max_digit = 0; 159 radix = 10; 160
- 基数を求める
161 /* First, interpret the radix. */
162 if (*str == '0')
163 {
164 radix = 8;
165 str++;
166
167 /* Require at least one hex digit to classify it as hex. */
168 if ((*str == 'x' || *str == 'X')
169 && (str[1] == '.' || ISXDIGIT (str[1])))
170 {
171 radix = 16;
172 str++;
173 }
174 }
175
- 数字列の最後までスキャンして正しい様式になっているか調べる
176 /* Now scan for a well-formed integer or float. */
177 for (;;)
178 {
179 unsigned int c = *str++;
180
181 if (ISDIGIT (c) || (ISXDIGIT (c) && radix == 16))
182 {
183 c = hex_value (c);
184 if (c > max_digit)
185 max_digit = c;
186 }
187 else if (c == '.')
188 {
189 if (float_flag == NOT_FLOAT)
190 float_flag = AFTER_POINT;
191 else
192 SYNTAX_ERROR ("too many decimal points in number");
193 }
194 else if ((radix <= 10 && (c == 'e' || c == 'E'))
195 || (radix == 16 && (c == 'p' || c == 'P')))
196 {
197 float_flag = AFTER_EXPON;
198 break;
199 }
200 else
201 {
202 /* Start of suffix. */
203 str--;
204 break;
205 }
206 }
207
- 浮動小数点で基数8のときは基数10に置き換える
- 些細なエラー処理か何かか?
208 if (float_flag != NOT_FLOAT && radix == 8) 209 radix = 10; 210
- 基数以上の値を使うのはエラー
211 if (max_digit >= radix) 212 SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit); 213
- 浮動小数点の処理
214 if (float_flag != NOT_FLOAT)
215 {
216 if (radix == 16 && CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, c99))
217 cpp_error (pfile, CPP_DL_PEDWARN,
218 "use of C99 hexadecimal floating constant");
219
220 if (float_flag == AFTER_EXPON)
221 {
222 if (*str == '+' || *str == '-')
223 str++;
224
225 /* Exponent is decimal, even if string is a hex float. */
226 if (!ISDIGIT (*str))
227 SYNTAX_ERROR ("exponent has no digits");
228
229 do
230 str++;
231 while (ISDIGIT (*str));
232 }
233 else if (radix == 16)
234 SYNTAX_ERROR ("hexadecimal floating constants require an exponent");
235
- 後置詞の処理
236 result = interpret_float_suffix (str, limit - str); 237 if (result == 0) 238 { 239 cpp_error (pfile, CPP_DL_ERROR, 240 "invalid suffix \"%.*s\" on floating constant", 241 (int) (limit - str), str); 242 return CPP_N_INVALID; 243 } 244
- 伝統的なCだと浮動小数点型の後置詞を許さない
245 /* Traditional C didn't accept any floating suffixes. */ 246 if (limit != str 247 && CPP_WTRADITIONAL (pfile) 248 && ! cpp_sys_macro_p (pfile)) 249 cpp_error (pfile, CPP_DL_WARNING, 250 "traditional C rejects the \"%.*s\" suffix", 251 (int) (limit - str), str); 252 253 result |= CPP_N_FLOATING; 254 }
- 整数型の処理
255 else
256 {
- 後置詞の処理
257 result = interpret_int_suffix (str, limit - str); 258 if (result == 0) 259 { 260 cpp_error (pfile, CPP_DL_ERROR, 261 "invalid suffix \"%.*s\" on integer constant", 262 (int) (limit - str), str); 263 return CPP_N_INVALID; 264 } 265 266 /* Traditional C only accepted the 'L' suffix. 267 Suppress warning about 'LL' with -Wno-long-long. */ 268 if (CPP_WTRADITIONAL (pfile) && ! cpp_sys_macro_p (pfile)) 269 { 270 int u_or_i = (result & (CPP_N_UNSIGNED|CPP_N_IMAGINARY)); 271 int large = (result & CPP_N_WIDTH) == CPP_N_LARGE; 272 273 if (u_or_i || (large && CPP_OPTION (pfile, warn_long_long))) 274 cpp_error (pfile, CPP_DL_WARNING, 275 "traditional C rejects the \"%.*s\" suffix", 276 (int) (limit - str), str); 277 } 278 279 if ((result & CPP_N_WIDTH) == CPP_N_LARGE 280 && ! CPP_OPTION (pfile, c99) 281 && CPP_OPTION (pfile, warn_long_long)) 282 cpp_error (pfile, CPP_DL_PEDWARN, 283 "use of C99 long long integer constant"); 284 285 result |= CPP_N_INTEGER; 286 } 287 288 if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile)) 289 cpp_error (pfile, CPP_DL_PEDWARN, 290 "imaginary constants are a GCC extension"); 291
- 基数の処理
292 if (radix == 10) 293 result |= CPP_N_DECIMAL; 294 else if (radix == 16) 295 result |= CPP_N_HEX; 296 else 297 result |= CPP_N_OCTAL; 298 299 return result; 300
- SYNTAX_ERROR, SYNTAX_ERROR2はマクロで、最後の所がここへのgoto文になっている
301 syntax_error: 302 return CPP_N_INVALID; 303 }