GCC Wikia
Advertisement

このページを編集する際は,編集に関する方針に従ってください.[]

概要[]

  • gcc-4.1.0/libcpp/expr.cにて定義
  • 数値型を解析して正しいフラグをたてる
    • 整数型か、浮動小数点型か
    • 大きさ(バイト数)はどのくらいか
    • 虚数なのか
  • 複数の規格に対応するためのコードが結構ある

引数[]

実装[]

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 

301  syntax_error:
302   return CPP_N_INVALID;
303 }



リンク元

Advertisement