Commit f1d723c6 by Zhenyao Mo Committed by Jamie Madill

Clamp numeric overflow rather than failing with an error

BUG=249086 ANGLEBUG=468 TEST= R=alokp@chromium.org, kbr@chromium.org Review URL: https://codereview.appspot.com/13195043
parent b41ebf57
#define MAJOR_VERSION 2 #define MAJOR_VERSION 2
#define MINOR_VERSION 0 #define MINOR_VERSION 0
#define BUILD_VERSION 0 #define BUILD_VERSION 0
#define BUILD_REVISION 2011 #define BUILD_REVISION 2012
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x) #define MACRO_STRINGIFY(x) STRINGIFY(x)
......
...@@ -61,6 +61,8 @@ static int ES2_reserved_ES3_keyword(TParseContext *context, int token); ...@@ -61,6 +61,8 @@ static int ES2_reserved_ES3_keyword(TParseContext *context, int token);
static int ES2_keyword_ES3_reserved(TParseContext *context, int token); static int ES2_keyword_ES3_reserved(TParseContext *context, int token);
static int ES2_ident_ES3_keyword(TParseContext *context, int token); static int ES2_ident_ES3_keyword(TParseContext *context, int token);
static int uint_constant(TParseContext *context); static int uint_constant(TParseContext *context);
static int int_constant(yyscan_t yyscanner);
static int float_constant(yyscan_t yyscanner);
static int floatsuffix_check(TParseContext* context); static int floatsuffix_check(TParseContext* context);
%} %}
...@@ -307,17 +309,17 @@ O [0-7] ...@@ -307,17 +309,17 @@ O [0-7]
return check_type(yyscanner); return check_type(yyscanner);
} }
0[xX]{H}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; } 0[xX]{H}+ { return int_constant(yyscanner); }
0{O}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; } 0{O}+ { return int_constant(yyscanner); }
{D}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; } {D}+ { return int_constant(yyscanner); }
0[xX]{H}+[uU] { return uint_constant(context); } 0[xX]{H}+[uU] { return uint_constant(context); }
0{O}+[uU] { return uint_constant(context); } 0{O}+[uU] { return uint_constant(context); }
{D}+[uU] { return uint_constant(context); } {D}+[uU] { return uint_constant(context); }
{D}+{E} { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; } {D}+{E} { return float_constant(yyscanner); }
{D}+"."{D}*({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; } {D}+"."{D}*({E})? { return float_constant(yyscanner); }
"."{D}+({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; } "."{D}+({E})? { return float_constant(yyscanner); }
{D}+{E}[fF] { return floatsuffix_check(context); } {D}+{E}[fF] { return floatsuffix_check(context); }
{D}+"."{D}*({E})?[fF] { return floatsuffix_check(context); } {D}+"."{D}*({E})?[fF] { return floatsuffix_check(context); }
...@@ -459,8 +461,6 @@ int uint_constant(TParseContext *context) ...@@ -459,8 +461,6 @@ int uint_constant(TParseContext *context)
struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
yyscan_t yyscanner = (yyscan_t) context->scanner; yyscan_t yyscanner = (yyscan_t) context->scanner;
yylval->lex.u = static_cast<unsigned int>(strtol(yytext, 0, 0));
if (context->shaderVersion < 300) if (context->shaderVersion < 300)
{ {
context->error(*yylloc, "Unsigned integers are unsupported prior to GLSL ES 3.00", yytext, ""); context->error(*yylloc, "Unsigned integers are unsupported prior to GLSL ES 3.00", yytext, "");
...@@ -468,6 +468,9 @@ int uint_constant(TParseContext *context) ...@@ -468,6 +468,9 @@ int uint_constant(TParseContext *context)
return 0; return 0;
} }
if (!atoi_clamp(yytext, &(yylval->lex.i)))
yyextra->warning(*yylloc, "Integer overflow", yytext, "");
return UINTCONSTANT; return UINTCONSTANT;
} }
...@@ -475,8 +478,6 @@ int floatsuffix_check(TParseContext* context) ...@@ -475,8 +478,6 @@ int floatsuffix_check(TParseContext* context)
{ {
struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
yylval->lex.f = static_cast<float>(atof_dot(yytext));
if (context->shaderVersion < 300) if (context->shaderVersion < 300)
{ {
context->error(*yylloc, "Floating-point suffix unsupported prior to GLSL ES 3.00", yytext); context->error(*yylloc, "Floating-point suffix unsupported prior to GLSL ES 3.00", yytext);
...@@ -484,6 +485,9 @@ int floatsuffix_check(TParseContext* context) ...@@ -484,6 +485,9 @@ int floatsuffix_check(TParseContext* context)
return 0; return 0;
} }
if (!atof_clamp(yytext, &(yylval->lex.f)))
yyextra->warning(*yylloc, "Float overflow", yytext, "");
return(FLOATCONSTANT); return(FLOATCONSTANT);
} }
...@@ -492,6 +496,22 @@ void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) { ...@@ -492,6 +496,22 @@ void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) {
context->recover(); context->recover();
} }
int int_constant(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
if (!atoi_clamp(yytext, &(yylval->lex.i)))
yyextra->warning(*yylloc, "Integer overflow", yytext, "");
return INTCONSTANT;
}
int float_constant(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
if (!atof_clamp(yytext, &(yylval->lex.f)))
yyextra->warning(*yylloc, "Float overflow", yytext, "");
return FLOATCONSTANT;
}
int glslang_initialize(TParseContext* context) { int glslang_initialize(TParseContext* context) {
yyscan_t scanner = NULL; yyscan_t scanner = NULL;
if (yylex_init_extra(context, &scanner)) if (yylex_init_extra(context, &scanner))
......
...@@ -1020,6 +1020,8 @@ static int ES2_reserved_ES3_keyword(TParseContext *context, int token); ...@@ -1020,6 +1020,8 @@ static int ES2_reserved_ES3_keyword(TParseContext *context, int token);
static int ES2_keyword_ES3_reserved(TParseContext *context, int token); static int ES2_keyword_ES3_reserved(TParseContext *context, int token);
static int ES2_ident_ES3_keyword(TParseContext *context, int token); static int ES2_ident_ES3_keyword(TParseContext *context, int token);
static int uint_constant(TParseContext *context); static int uint_constant(TParseContext *context);
static int int_constant(yyscan_t yyscanner);
static int float_constant(yyscan_t yyscanner);
static int floatsuffix_check(TParseContext* context); static int floatsuffix_check(TParseContext* context);
#define INITIAL 0 #define INITIAL 0
...@@ -1793,15 +1795,15 @@ YY_RULE_SETUP ...@@ -1793,15 +1795,15 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 178: case 178:
YY_RULE_SETUP YY_RULE_SETUP
{ yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; } { return int_constant(yyscanner); }
YY_BREAK YY_BREAK
case 179: case 179:
YY_RULE_SETUP YY_RULE_SETUP
{ yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; } { return int_constant(yyscanner); }
YY_BREAK YY_BREAK
case 180: case 180:
YY_RULE_SETUP YY_RULE_SETUP
{ yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; } { return int_constant(yyscanner); }
YY_BREAK YY_BREAK
case 181: case 181:
YY_RULE_SETUP YY_RULE_SETUP
...@@ -1817,15 +1819,15 @@ YY_RULE_SETUP ...@@ -1817,15 +1819,15 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 184: case 184:
YY_RULE_SETUP YY_RULE_SETUP
{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; } { return float_constant(yyscanner); }
YY_BREAK YY_BREAK
case 185: case 185:
YY_RULE_SETUP YY_RULE_SETUP
{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; } { return float_constant(yyscanner); }
YY_BREAK YY_BREAK
case 186: case 186:
YY_RULE_SETUP YY_RULE_SETUP
{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; } { return float_constant(yyscanner); }
YY_BREAK YY_BREAK
case 187: case 187:
YY_RULE_SETUP YY_RULE_SETUP
...@@ -3261,8 +3263,6 @@ int uint_constant(TParseContext *context) ...@@ -3261,8 +3263,6 @@ int uint_constant(TParseContext *context)
struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
yyscan_t yyscanner = (yyscan_t) context->scanner; yyscan_t yyscanner = (yyscan_t) context->scanner;
yylval->lex.u = static_cast<unsigned int>(strtol(yytext, 0, 0));
if (context->shaderVersion < 300) if (context->shaderVersion < 300)
{ {
context->error(*yylloc, "Unsigned integers are unsupported prior to GLSL ES 3.00", yytext, ""); context->error(*yylloc, "Unsigned integers are unsupported prior to GLSL ES 3.00", yytext, "");
...@@ -3270,6 +3270,9 @@ int uint_constant(TParseContext *context) ...@@ -3270,6 +3270,9 @@ int uint_constant(TParseContext *context)
return 0; return 0;
} }
if (!atoi_clamp(yytext, &(yylval->lex.i)))
yyextra->warning(*yylloc, "Integer overflow", yytext, "");
return UINTCONSTANT; return UINTCONSTANT;
} }
...@@ -3277,8 +3280,6 @@ int floatsuffix_check(TParseContext* context) ...@@ -3277,8 +3280,6 @@ int floatsuffix_check(TParseContext* context)
{ {
struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
yylval->lex.f = static_cast<float>(atof_dot(yytext));
if (context->shaderVersion < 300) if (context->shaderVersion < 300)
{ {
context->error(*yylloc, "Floating-point suffix unsupported prior to GLSL ES 3.00", yytext); context->error(*yylloc, "Floating-point suffix unsupported prior to GLSL ES 3.00", yytext);
...@@ -3286,6 +3287,9 @@ int floatsuffix_check(TParseContext* context) ...@@ -3286,6 +3287,9 @@ int floatsuffix_check(TParseContext* context)
return 0; return 0;
} }
if (!atof_clamp(yytext, &(yylval->lex.f)))
yyextra->warning(*yylloc, "Float overflow", yytext, "");
return(FLOATCONSTANT); return(FLOATCONSTANT);
} }
...@@ -3294,6 +3298,22 @@ void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) { ...@@ -3294,6 +3298,22 @@ void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) {
context->recover(); context->recover();
} }
int int_constant(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
if (!atoi_clamp(yytext, &(yylval->lex.i)))
yyextra->warning(*yylloc, "Integer overflow", yytext, "");
return INTCONSTANT;
}
int float_constant(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
if (!atof_clamp(yytext, &(yylval->lex.f)))
yyextra->warning(*yylloc, "Float overflow", yytext, "");
return FLOATCONSTANT;
}
int glslang_initialize(TParseContext* context) { int glslang_initialize(TParseContext* context) {
yyscan_t scanner = NULL; yyscan_t scanner = NULL;
if (yylex_init_extra(context,&scanner)) if (yylex_init_extra(context,&scanner))
......
/* A Bison parser, made by GNU Bison 2.7. */ /* A Bison parser, made by GNU Bison 2.7.1. */
/* Bison implementation for Yacc-like parsers in C /* Bison implementation for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc. Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#define YYBISON 1 #define YYBISON 1
/* Bison version. */ /* Bison version. */
#define YYBISON_VERSION "2.7" #define YYBISON_VERSION "2.7.1"
/* Skeleton name. */ /* Skeleton name. */
#define YYSKELETON_NAME "yacc.c" #define YYSKELETON_NAME "yacc.c"
...@@ -258,6 +258,14 @@ typedef short int yytype_int16; ...@@ -258,6 +258,14 @@ typedef short int yytype_int16;
# endif # endif
#endif #endif
#ifndef __attribute__
/* This feature is available in gcc versions 2.5 and later. */
# if (! defined __GNUC__ || __GNUC__ < 2 \
|| (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
# define __attribute__(Spec) /* empty */
# endif
#endif
/* Suppress unused-variable warnings by "using" E. */ /* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__ #if ! defined lint || defined __GNUC__
# define YYUSE(E) ((void) (E)) # define YYUSE(E) ((void) (E))
...@@ -265,6 +273,7 @@ typedef short int yytype_int16; ...@@ -265,6 +273,7 @@ typedef short int yytype_int16;
# define YYUSE(E) /* empty */ # define YYUSE(E) /* empty */
#endif #endif
/* Identity function, used to suppress warnings about constant conditions. */ /* Identity function, used to suppress warnings about constant conditions. */
#ifndef lint #ifndef lint
# define YYID(N) (N) # define YYID(N) (N)
...@@ -762,11 +771,7 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, context) ...@@ -762,11 +771,7 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, context)
# else # else
YYUSE (yyoutput); YYUSE (yyoutput);
# endif # endif
switch (yytype) YYUSE (yytype);
{
default:
break;
}
} }
...@@ -1160,12 +1165,7 @@ yydestruct (yymsg, yytype, yyvaluep, context) ...@@ -1160,12 +1165,7 @@ yydestruct (yymsg, yytype, yyvaluep, context)
yymsg = "Deleting"; yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
switch (yytype) YYUSE (yytype);
{
default:
break;
}
} }
......
...@@ -95,34 +95,6 @@ void Preprocessor::lex(Token* token) ...@@ -95,34 +95,6 @@ void Preprocessor::lex(Token* token)
case Token::PP_HASH: case Token::PP_HASH:
assert(false); assert(false);
break; break;
case Token::CONST_INT:
{
int val = 0;
if (!token->iValue(&val))
{
// Do not mark the token as invalid.
// Just emit the diagnostic and reset value to 0.
mImpl->diagnostics->report(Diagnostics::INTEGER_OVERFLOW,
token->location, token->text);
token->text.assign("0");
}
validToken = true;
break;
}
case Token::CONST_FLOAT:
{
float val = 0;
if (!token->fValue(&val))
{
// Do not mark the token as invalid.
// Just emit the diagnostic and reset value to 0.0.
mImpl->diagnostics->report(Diagnostics::FLOAT_OVERFLOW,
token->location, token->text);
token->text.assign("0.0");
}
validToken = true;
break;
}
case Token::PP_NUMBER: case Token::PP_NUMBER:
mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER, mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER,
token->location, token->text); token->location, token->text);
...@@ -139,4 +111,3 @@ void Preprocessor::lex(Token* token) ...@@ -139,4 +111,3 @@ void Preprocessor::lex(Token* token)
} }
} // namespace pp } // namespace pp
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#define FLEX_SCANNER #define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_MINOR_VERSION 5
#define YY_FLEX_SUBMINOR_VERSION 35 #define YY_FLEX_SUBMINOR_VERSION 37
#if YY_FLEX_SUBMINOR_VERSION > 0 #if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA #define FLEX_BETA
#endif #endif
...@@ -64,7 +64,6 @@ typedef int flex_int32_t; ...@@ -64,7 +64,6 @@ typedef int flex_int32_t;
typedef unsigned char flex_uint8_t; typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t; typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t; typedef unsigned int flex_uint32_t;
#endif /* ! C99 */
/* Limits of integral types. */ /* Limits of integral types. */
#ifndef INT8_MIN #ifndef INT8_MIN
...@@ -95,6 +94,8 @@ typedef unsigned int flex_uint32_t; ...@@ -95,6 +94,8 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U) #define UINT32_MAX (4294967295U)
#endif #endif
#endif /* ! C99 */
#endif /* ! FLEXINT_H */ #endif /* ! FLEXINT_H */
#ifdef __cplusplus #ifdef __cplusplus
...@@ -185,6 +186,11 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE; ...@@ -185,6 +186,11 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE;
typedef size_t yy_size_t; typedef size_t yy_size_t;
#endif #endif
#ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
typedef size_t yy_size_t;
#endif
#define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2 #define EOB_ACT_LAST_MATCH 2
...@@ -335,7 +341,7 @@ void ppfree (void * ,yyscan_t yyscanner ); ...@@ -335,7 +341,7 @@ void ppfree (void * ,yyscan_t yyscanner );
/* Begin user sect3 */ /* Begin user sect3 */
#define ppwrap(n) 1 #define ppwrap(yyscanner) 1
#define YY_SKIP_YYWRAP #define YY_SKIP_YYWRAP
typedef unsigned char YY_CHAR; typedef unsigned char YY_CHAR;
...@@ -661,6 +667,10 @@ int ppget_lineno (yyscan_t yyscanner ); ...@@ -661,6 +667,10 @@ int ppget_lineno (yyscan_t yyscanner );
void ppset_lineno (int line_number ,yyscan_t yyscanner ); void ppset_lineno (int line_number ,yyscan_t yyscanner );
int ppget_column (yyscan_t yyscanner );
void ppset_column (int column_no ,yyscan_t yyscanner );
YYSTYPE * ppget_lval (yyscan_t yyscanner ); YYSTYPE * ppget_lval (yyscan_t yyscanner );
void ppset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); void ppset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
...@@ -709,7 +719,7 @@ static int input (yyscan_t yyscanner ); ...@@ -709,7 +719,7 @@ static int input (yyscan_t yyscanner );
/* This used to be an fputs(), but since the string might contain NUL's, /* This used to be an fputs(), but since the string might contain NUL's,
* we now use fwrite(). * we now use fwrite().
*/ */
#define ECHO fwrite( yytext, yyleng, 1, yyout ) #define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
#endif #endif
/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
...@@ -720,7 +730,7 @@ static int input (yyscan_t yyscanner ); ...@@ -720,7 +730,7 @@ static int input (yyscan_t yyscanner );
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \ { \
int c = '*'; \ int c = '*'; \
yy_size_t n; \ size_t n; \
for ( n = 0; n < max_size && \ for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \ buf[n] = (char) c; \
...@@ -1361,7 +1371,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) ...@@ -1361,7 +1371,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
{ /* Not enough room in the buffer - grow it. */ { /* Not enough room in the buffer - grow it. */
/* just a shorter name for the current buffer */ /* just a shorter name for the current buffer */
YY_BUFFER_STATE b = YY_CURRENT_BUFFER; YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
int yy_c_buf_p_offset = int yy_c_buf_p_offset =
(int) (yyg->yy_c_buf_p - b->yy_ch_buf); (int) (yyg->yy_c_buf_p - b->yy_ch_buf);
...@@ -1496,6 +1506,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) ...@@ -1496,6 +1506,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
yy_is_jam = (yy_current_state == 97); yy_is_jam = (yy_current_state == 97);
(void)yyg;
return yy_is_jam ? 0 : yy_current_state; return yy_is_jam ? 0 : yy_current_state;
} }
...@@ -1897,8 +1908,8 @@ YY_BUFFER_STATE pp_scan_string (yyconst char * yystr , yyscan_t yyscanner) ...@@ -1897,8 +1908,8 @@ YY_BUFFER_STATE pp_scan_string (yyconst char * yystr , yyscan_t yyscanner)
/** Setup the input buffer state to scan the given bytes. The next call to pplex() will /** Setup the input buffer state to scan the given bytes. The next call to pplex() will
* scan from a @e copy of @a bytes. * scan from a @e copy of @a bytes.
* @param bytes the byte buffer to scan * @param yybytes the byte buffer to scan
* @param len the number of bytes in the buffer pointed to by @a bytes. * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
* @param yyscanner The scanner object. * @param yyscanner The scanner object.
* @return the newly allocated buffer state object. * @return the newly allocated buffer state object.
*/ */
...@@ -1906,7 +1917,8 @@ YY_BUFFER_STATE pp_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ...@@ -1906,7 +1917,8 @@ YY_BUFFER_STATE pp_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len
{ {
YY_BUFFER_STATE b; YY_BUFFER_STATE b;
char *buf; char *buf;
yy_size_t n, i; yy_size_t n;
yy_size_t i;
/* Get memory for full buffer, including space for trailing EOB's. */ /* Get memory for full buffer, including space for trailing EOB's. */
n = _yybytes_len + 2; n = _yybytes_len + 2;
...@@ -2052,7 +2064,7 @@ void ppset_lineno (int line_number , yyscan_t yyscanner) ...@@ -2052,7 +2064,7 @@ void ppset_lineno (int line_number , yyscan_t yyscanner)
/* lineno is only valid if an input buffer exists. */ /* lineno is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER ) if (! YY_CURRENT_BUFFER )
yy_fatal_error( "ppset_lineno called with no buffer" , yyscanner); YY_FATAL_ERROR( "ppset_lineno called with no buffer" );
yylineno = line_number; yylineno = line_number;
} }
...@@ -2067,7 +2079,7 @@ void ppset_column (int column_no , yyscan_t yyscanner) ...@@ -2067,7 +2079,7 @@ void ppset_column (int column_no , yyscan_t yyscanner)
/* column is only valid if an input buffer exists. */ /* column is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER ) if (! YY_CURRENT_BUFFER )
yy_fatal_error( "ppset_column called with no buffer" , yyscanner); YY_FATAL_ERROR( "ppset_column called with no buffer" );
yycolumn = column_no; yycolumn = column_no;
} }
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include <cerrno>
#include <limits>
#include "util.h" #include "util.h"
#ifdef _MSC_VER #ifdef _MSC_VER
...@@ -15,19 +18,39 @@ ...@@ -15,19 +18,39 @@
#include <sstream> #include <sstream>
#endif #endif
double atof_dot(const char *str) bool atof_clamp(const char *str, float *value)
{ {
bool success = true;
#ifdef _MSC_VER #ifdef _MSC_VER
_locale_t l = _create_locale(LC_NUMERIC, "C"); _locale_t l = _create_locale(LC_NUMERIC, "C");
double result = _atof_l(str, l); double dvalue = _atof_l(str, l);
_free_locale(l); _free_locale(l);
return result; if (errno == ERANGE || dvalue > std::numeric_limits<float>::max())
success = false;
else
*value = static_cast<float>(dvalue);
#else #else
double result;
std::istringstream s(str); std::istringstream s(str);
std::locale l("C"); std::locale l("C");
s.imbue(l); s.imbue(l);
s >> result; s >> *value;
return result; if (s.fail())
success = false;
#endif #endif
if (!success)
*value = std::numeric_limits<float>::max();
return success;
} }
bool atoi_clamp(const char *str, int *value)
{
long int lvalue = strtol(str, 0, 0);
if (errno == ERANGE || lvalue > std::numeric_limits<int>::max())
{
*value = std::numeric_limits<int>::max();
return false;
}
*value = static_cast<int>(lvalue);
return true;
}
...@@ -7,15 +7,14 @@ ...@@ -7,15 +7,14 @@
#ifndef COMPILER_UTIL_H #ifndef COMPILER_UTIL_H
#define COMPILER_UTIL_H #define COMPILER_UTIL_H
#ifdef __cplusplus // atof_clamp is like atof but
extern "C" { // 1. it forces C locale, i.e. forcing '.' as decimal point.
#endif // 2. it clamps the value to -FLT_MAX or FLT_MAX if overflow happens.
// Return false if overflow happens.
extern bool atof_clamp(const char *str, float *value);
// atof_dot is like atof but forcing C locale, i.e. forcing '.' as decimal point. // If overflow happens, clamp the value to INT_MIN or INT_MAX.
double atof_dot(const char *str); // Return false if overflow happens.
extern bool atoi_clamp(const char *str, int *value);
#ifdef __cplusplus
} // end extern "C"
#endif
#endif // COMPILER_UTIL_H #endif // COMPILER_UTIL_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment