diff --git a/src/config.c b/src/config.c index e280bd4f..637e4f3c 100644 --- a/src/config.c +++ b/src/config.c @@ -288,9 +288,15 @@ void free_tokens(int n, ...) TOKEN *new_number(const char *text) { + const char *errstr; struct token_t *tkn = new_token(TKN_NUMBER); tkn->value.type = V_NUM; - tkn->value.number = atoi(text); + tkn->value.number = str_int(text, STR_INT32, &errstr); + if(errstr) { + yyerror("integer %s in config file: %s", text, errstr); + free_token(tkn); + return NULL; + } #if DEBUG msg_info("NUMBER(%d)\n", tkn->value.number); @@ -300,31 +306,18 @@ TOKEN *new_number(const char *text) { } TOKEN *new_number_real(const char *text) { + char *endptr; struct token_t * tkn = new_token(TKN_NUMBER); tkn->value.type = V_NUM_REAL; - tkn->value.number_real = atof(text); - -#if DEBUG - msg_info("NUMBER(%g)\n", tkn->value.number_real); -#endif - - return tkn; -} - -TOKEN *new_hexnumber(const char *text) { - struct token_t *tkn = new_token(TKN_NUMBER); - char * e; - - tkn->value.type = V_NUM; - tkn->value.number = strtoul(text, &e, 16); - if ((e == text) || (*e != 0)) { - yyerror("cannot scan hex number %s", text); + tkn->value.number_real = strtod(text, &endptr); + if(endptr == text || *endptr) { + yyerror("real number in config file %s: parsing error", text); free_token(tkn); return NULL; } - + #if DEBUG - msg_info("HEXNUMBER(%d)\n", tkn->value.number); + msg_info("NUMBER(%g)\n", tkn->value.number_real); #endif return tkn; diff --git a/src/config.h b/src/config.h index 0f10f801..6495e40c 100644 --- a/src/config.h +++ b/src/config.h @@ -128,8 +128,6 @@ TOKEN *new_number(const char *text); TOKEN *new_number_real(const char *text); -TOKEN *new_hexnumber(const char *text); - TOKEN *new_constant(const char *text); TOKEN *new_string(const char *text); diff --git a/src/lexer.l b/src/lexer.l index 7b811bad..7d79168f 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -20,7 +20,6 @@ /* $Id$ */ %{ -/* need this for the call to atof() below */ #include #include #include @@ -50,9 +49,27 @@ static void adjust_cfg_lineno(const char *p) { %} -DIGIT [0-9] -HEXDIGIT [0-9a-fA-F] -SIGN [+-] + // AVRDUDE integer size suffix (LL/L/S/H/HH) +SIZS ([lL][lL]|[lL]|[sS]|[hH]|[hH][hH]) + // AVRDUDE integer suffix incl unsigned designator +ISUF ([uU]|[uU]{SIZS}|{SIZS}[uU]|{SIZS}) + // Non-negative integers +INUM (0|[1-9][0-9]*){ISUF}? + // Octal integers +ONUM 0[0-7]+{ISUF}? + // Binary integers +BNUM 0[bB][01]+{ISUF}? + // Hexadecimal integers - fractional hexadecimals are treated below +XNUM 0[xX][0-9A-Fa-f]+{ISUF}? +RNUM (M{0,3})(D?C{0,3}|CM|CD)(L?X{0,3}|XC|XL)(V?I{0,3}|IX|IV) + + // Real numbers (decimal and hexadecimal fractional numbers) +SIGN [+-] +DNUM (([0-9]+[eE][-+]?[0-9]+)|([0-9]*\.[0-9]+([eE][-+]?[0-9]+)?)) +HNUM (0[xX](([0-9A-Fa-f]+([pP][-+]?[0-9]+))|([0-9A-Fa-f]*\.[0-9A-Fa-f]+([pP][-+]?[0-9]+)?))) +NAN [Nn][Aa][Nn] +INF [Ii][Nn][Ff]([Ii][Nn][Ii][Tt][Yy])? + %option nounput @@ -63,9 +80,21 @@ SIGN [+-] %% -{DIGIT}+ { yylval = new_number(yytext); return TKN_NUMBER; /* sign is treated in grammar */ } -{SIGN}?{DIGIT}+"."{DIGIT}* { yylval = new_number_real(yytext); return TKN_NUMBER_REAL; } -{SIGN}?"."{DIGIT}+ { yylval = new_number_real(yytext); return TKN_NUMBER_REAL; } +({INUM}|{BNUM}|{ONUM}|{XNUM}|{RNUM}) { /* sign is treated in grammar */ + yylval = new_number(yytext); + if(!yylval) + return YYERRCODE; + + return TKN_NUMBER; +} + +{SIGN}?({DNUM}|{HNUM}|{NAN}|{INF}) { + yylval = new_number_real(yytext); + if(!yylval) + return YYERRCODE; + + return TKN_NUMBER_REAL; +} ["]([^"\\\n]|\\.|\\\n)*["] { char *str= cfg_strdup("lexer.l", yytext); @@ -78,8 +107,6 @@ SIGN [+-] return TKN_STRING; } -0x{HEXDIGIT}+ { yylval = new_hexnumber(yytext); return TKN_NUMBER; } - #\n#\ PROGRAMMER\ DEFINITIONS\n#\n+ { /* Record comments so far as prologue and skip */ cfg_capture_prologue(); adjust_cfg_lineno(yytext);