00001 #include <stdio.h>
00002 #include <inttypes.h>
00003 #include <ctype.h>
00004 #include <string.h>
00005
00006 #include "parse.h"
00007 #include "parse_num.h"
00008
00009
00010 #define debug_printf(args...) do {} while(0)
00011
00012
00013 #define U08_MIN 0x00
00014 #define U08_MAX 0xFF
00015 #define U16_MIN 0x0000
00016 #define U16_MAX 0xFFFF
00017 #define U32_MIN 0x00000000
00018 #define U32_MAX 0xFFFFFFFF
00019 #define S08_MIN 0x80
00020 #define S08_MAX 0x7F
00021 #define S16_MIN 0x8000
00022 #define S16_MAX 0x7FFF
00023 #define S32_MIN 0x80000000
00024 #define S32_MAX 0x7FFFFFFF
00025
00026
00027 struct token_ops token_num_ops = {
00028 .parse = parse_num,
00029 .complete_get_nb = NULL,
00030 .complete_get_elt = NULL,
00031 .get_help = get_help_num,
00032 };
00033
00034
00035 enum num_parse_state_t {
00036 START,
00037 DEC_NEG,
00038 BIN,
00039 HEX,
00040 FLOAT_POS,
00041 FLOAT_NEG,
00042 ERROR,
00043
00044 FIRST_OK,
00045 ZERO_OK,
00046 HEX_OK,
00047 OCTAL_OK,
00048 BIN_OK,
00049 DEC_NEG_OK,
00050 DEC_POS_OK,
00051 FLOAT_POS_OK,
00052 FLOAT_NEG_OK,
00053 };
00054
00055
00056 static const prog_char help1[] = "UINT8";
00057 static const prog_char help2[] = "UINT16";
00058 static const prog_char help3[] = "UINT32";
00059 static const prog_char help4[] = "INT8";
00060 static const prog_char help5[] = "INT16";
00061 static const prog_char help6[] = "INT32";
00062 #ifndef CONFIG_MODULE_PARSE_NO_FLOAT
00063 static const prog_char help7[] = "FLOAT";
00064 #endif
00065 static const prog_char * num_help[] = {
00066 help1, help2, help3, help4,
00067 help5, help6,
00068 #ifndef CONFIG_MODULE_PARSE_NO_FLOAT
00069 help7,
00070 #endif
00071 };
00072
00073 static inline int8_t
00074 add_to_res(uint8_t c, uint32_t * res, uint8_t base)
00075 {
00076
00077 if ( (U32_MAX - c) / base < *res ) {
00078 return -1;
00079 }
00080
00081 *res = *res * base + c ;
00082 return 0;
00083 }
00084
00085
00086
00087 int8_t
00088 parse_num(parse_pgm_token_hdr_t * tk, const char * srcbuf, void * res)
00089 {
00090 struct token_num_data nd;
00091 enum num_parse_state_t st = START;
00092 const char * buf = srcbuf;
00093 char c = *buf;
00094 uint32_t res1=0, res2=0, res3=1;
00095
00096 memcpy_P(&nd, &((struct token_num *)tk)->num_data, sizeof(nd));
00097
00098 while ( st != ERROR && c && ! isendoftoken(c) ) {
00099 debug_printf("%c %x -> ", c, c);
00100 switch (st) {
00101 case START:
00102 if (c == '-') {
00103 st = DEC_NEG;
00104 }
00105 else if (c == '0') {
00106 st = ZERO_OK;
00107 }
00108 #ifndef CONFIG_MODULE_PARSE_NO_FLOAT
00109 else if (c == '.') {
00110 st = FLOAT_POS;
00111 res1 = 0;
00112 }
00113 #endif
00114 else if (c >= '1' && c <= '9') {
00115 if (add_to_res(c - '0', &res1, 10) < 0)
00116 st = ERROR;
00117 else
00118 st = DEC_POS_OK;
00119 }
00120 else {
00121 st = ERROR;
00122 }
00123 break;
00124
00125 case ZERO_OK:
00126 if (c == 'x') {
00127 st = HEX;
00128 }
00129 else if (c == 'b') {
00130 st = BIN;
00131 }
00132 #ifndef CONFIG_MODULE_PARSE_NO_FLOAT
00133 else if (c == '.') {
00134 st = FLOAT_POS;
00135 res1 = 0;
00136 }
00137 #endif
00138 else if (c >= '0' && c <= '7') {
00139 if (add_to_res(c - '0', &res1, 10) < 0)
00140 st = ERROR;
00141 else
00142 st = OCTAL_OK;
00143 }
00144 else {
00145 st = ERROR;
00146 }
00147 break;
00148
00149 case DEC_NEG:
00150 if (c >= '0' && c <= '9') {
00151 if (add_to_res(c - '0', &res1, 10) < 0)
00152 st = ERROR;
00153 else
00154 st = DEC_NEG_OK;
00155 }
00156 #ifndef CONFIG_MODULE_PARSE_NO_FLOAT
00157 else if (c == '.') {
00158 res1 = 0;
00159 st = FLOAT_NEG;
00160 }
00161 #endif
00162 else {
00163 st = ERROR;
00164 }
00165 break;
00166
00167 case DEC_NEG_OK:
00168 if (c >= '0' && c <= '9') {
00169 if (add_to_res(c - '0', &res1, 10) < 0)
00170 st = ERROR;
00171 }
00172 #ifndef CONFIG_MODULE_PARSE_NO_FLOAT
00173 else if (c == '.') {
00174 st = FLOAT_NEG;
00175 }
00176 #endif
00177 else {
00178 st = ERROR;
00179 }
00180 break;
00181
00182 case DEC_POS_OK:
00183 if (c >= '0' && c <= '9') {
00184 if (add_to_res(c - '0', &res1, 10) < 0)
00185 st = ERROR;
00186 }
00187 #ifndef CONFIG_MODULE_PARSE_NO_FLOAT
00188 else if (c == '.') {
00189 st = FLOAT_POS;
00190 }
00191 #endif
00192 else {
00193 st = ERROR;
00194 }
00195 break;
00196
00197 case HEX:
00198 st = HEX_OK;
00199
00200 case HEX_OK:
00201 if (c >= '0' && c <= '9') {
00202 if (add_to_res(c - '0', &res1, 16) < 0)
00203 st = ERROR;
00204 }
00205 else if (c >= 'a' && c <= 'f') {
00206 if (add_to_res(c - 'a' + 10, &res1, 16) < 0)
00207 st = ERROR;
00208 }
00209 else if (c >= 'A' && c <= 'F') {
00210 if (add_to_res(c - 'A' + 10, &res1, 16) < 0)
00211 st = ERROR;
00212 }
00213 else {
00214 st = ERROR;
00215 }
00216 break;
00217
00218
00219 case OCTAL_OK:
00220 if (c >= '0' && c <= '7') {
00221 if (add_to_res(c - '0', &res1, 8) < 0)
00222 st = ERROR;
00223 }
00224 else {
00225 st = ERROR;
00226 }
00227 break;
00228
00229 case BIN:
00230 st = BIN_OK;
00231
00232 case BIN_OK:
00233 if (c >= '0' && c <= '1') {
00234 if (add_to_res(c - '0', &res1, 2) < 0)
00235 st = ERROR;
00236 }
00237 else {
00238 st = ERROR;
00239 }
00240 break;
00241
00242 #ifndef CONFIG_MODULE_PARSE_NO_FLOAT
00243 case FLOAT_POS:
00244 if (c >= '0' && c <= '9') {
00245 if (add_to_res(c - '0', &res2, 10) < 0)
00246 st = ERROR;
00247 else
00248 st = FLOAT_POS_OK;
00249 res3 = 10;
00250 }
00251 else {
00252 st = ERROR;
00253 }
00254 break;
00255
00256 case FLOAT_NEG:
00257 if (c >= '0' && c <= '9') {
00258 if (add_to_res(c - '0', &res2, 10) < 0)
00259 st = ERROR;
00260 else
00261 st = FLOAT_NEG_OK;
00262 res3 = 10;
00263 }
00264 else {
00265 st = ERROR;
00266 }
00267 break;
00268
00269 case FLOAT_POS_OK:
00270 if (c >= '0' && c <= '9') {
00271 if (add_to_res(c - '0', &res2, 10) < 0)
00272 st = ERROR;
00273 if (add_to_res(0, &res3, 10) < 0)
00274 st = ERROR;
00275 }
00276 else {
00277 st = ERROR;
00278 }
00279 break;
00280
00281 case FLOAT_NEG_OK:
00282 if (c >= '0' && c <= '9') {
00283 if (add_to_res(c - '0', &res2, 10) < 0)
00284 st = ERROR;
00285 if (add_to_res(0, &res3, 10) < 0)
00286 st = ERROR;
00287 }
00288 else {
00289 st = ERROR;
00290 }
00291 break;
00292 #endif
00293
00294 default:
00295 debug_printf("not impl ");
00296
00297 }
00298
00299
00300 debug_printf("(%d) (%d) (%d)\n", res1, res2, res3);
00301
00302 buf ++;
00303 c = *buf;
00304
00305
00306 if (buf-srcbuf > 127)
00307 return -1;
00308 }
00309
00310 switch (st) {
00311 case ZERO_OK:
00312 case DEC_POS_OK:
00313 case HEX_OK:
00314 case OCTAL_OK:
00315 case BIN_OK:
00316 if ( nd.type == INT8 && res1 <= S08_MAX ) {
00317 if (res)
00318 *(int8_t *)res = (int8_t) res1;
00319 return (buf-srcbuf);
00320 }
00321 else if ( nd.type == INT16 && res1 <= S16_MAX ) {
00322 if (res)
00323 *(int16_t *)res = (int16_t) res1;
00324 return (buf-srcbuf);
00325 }
00326 else if ( nd.type == INT32 && res1 <= S32_MAX ) {
00327 if (res)
00328 *(int32_t *)res = (int32_t) res1;
00329 return (buf-srcbuf);
00330 }
00331 else if ( nd.type == UINT8 && res1 <= U08_MAX ) {
00332 if (res)
00333 *(uint8_t *)res = (uint8_t) res1;
00334 return (buf-srcbuf);
00335 }
00336 else if (nd.type == UINT16 && res1 <= U16_MAX ) {
00337 if (res)
00338 *(uint16_t *)res = (uint16_t) res1;
00339 return (buf-srcbuf);
00340 }
00341 else if ( nd.type == UINT32 ) {
00342 if (res)
00343 *(uint32_t *)res = (uint32_t) res1;
00344 return (buf-srcbuf);
00345 }
00346 #ifndef CONFIG_MODULE_PARSE_NO_FLOAT
00347 else if ( nd.type == FLOAT ) {
00348 if (res)
00349 *(float *)res = (float)res1;
00350 return (buf-srcbuf);
00351 }
00352 #endif
00353 else {
00354 return -1;
00355 }
00356 break;
00357
00358 case DEC_NEG_OK:
00359 if ( nd.type == INT8 && res1 <= S08_MAX + 1 ) {
00360 if (res)
00361 *(int8_t *)res = - (int8_t) res1;
00362 return (buf-srcbuf);
00363 }
00364 else if ( nd.type == INT16 && res1 <= (uint16_t)S16_MAX + 1 ) {
00365 if (res)
00366 *(int16_t *)res = - (int16_t) res1;
00367 return (buf-srcbuf);
00368 }
00369 else if ( nd.type == INT32 && res1 <= (uint32_t)S32_MAX + 1 ) {
00370 if (res)
00371 *(int32_t *)res = - (int32_t) res1;
00372 return (buf-srcbuf);
00373 }
00374 #ifndef CONFIG_MODULE_PARSE_NO_FLOAT
00375 else if ( nd.type == FLOAT ) {
00376 if (res)
00377 *(float *)res = - (float)res1;
00378 return (buf-srcbuf);
00379 }
00380 #endif
00381 else {
00382 return -1;
00383 }
00384 break;
00385
00386 #ifndef CONFIG_MODULE_PARSE_NO_FLOAT
00387 case FLOAT_POS:
00388 case FLOAT_POS_OK:
00389 if ( nd.type == FLOAT ) {
00390 if (res)
00391 *(float *)res = (float)res1 + ((float)res2 / (float)res3);
00392 return (buf-srcbuf);
00393
00394 }
00395 else {
00396 return -1;
00397 }
00398 break;
00399
00400 case FLOAT_NEG:
00401 case FLOAT_NEG_OK:
00402 if ( nd.type == FLOAT ) {
00403 if (res)
00404 *(float *)res = - ((float)res1 + ((float)res2 / (float)res3));
00405 return (buf-srcbuf);
00406
00407 }
00408 else {
00409 return -1;
00410 }
00411 break;
00412 #endif
00413 default:
00414 debug_printf("error\n");
00415 return -1;
00416 }
00417 return -1;
00418 }
00419
00420
00421
00422 int8_t
00423 get_help_num(parse_pgm_token_hdr_t * tk, char * dstbuf, uint8_t size)
00424 {
00425 struct token_num_data nd;
00426
00427 memcpy_P(&nd, &((struct token_num *)tk)->num_data, sizeof(nd));
00428
00429
00430
00431
00432
00433 strncpy_P(dstbuf, num_help[nd.type], size);
00434 dstbuf[size-1] = '\0';
00435 return 0;
00436 }