diff --git a/src/cfgrammar.h b/src/cfgrammar.h index f336db5c0ca6e52651034095b14289e8ff2a0e26..fdfa7c5c6751070dc95f280b63bfb4dac39b3792 100644 --- a/src/cfgrammar.h +++ b/src/cfgrammar.h @@ -19,8 +19,8 @@ typedef struct HCFGrammar_ { * therefore we must avoid 0 as a token value because NULL means "not in set". */ typedef uintptr_t HCFToken; -static inline HCFToken char_token(char c) { return (0x100 | c); } -static inline char token_char(HCFToken t) { return (0xFF & t); } +static inline HCFToken char_token(uint8_t c) { return (0x100 | c); } +static inline uint8_t token_char(HCFToken t) { return (0xFF & t); } static const HCFToken end_token = 0x200; diff --git a/src/parsers/bits.c b/src/parsers/bits.c index 091e4e63c5a39d5ae85709ff8819e36e637e8df3..408ea29b7eecf38bc75ff5d041d4725b6dc8c1c4 100644 --- a/src/parsers/bits.c +++ b/src/parsers/bits.c @@ -17,6 +17,41 @@ static HParseResult* parse_bits(void* env, HParseState *state) { return make_result(state->arena, result); } +static HParsedToken *reshape_bits(const HParseResult *p, bool signedp) { + // XXX works only for whole bytes + // XXX assumes big-endian + assert(p->ast); + assert(p->ast->token_type == TT_SEQUENCE); + + HCountedArray *seq = p->ast->seq; + HParsedToken *ret = h_arena_malloc(p->arena, sizeof(HParsedToken)); + ret->token_type = TT_UINT; + + if(signedp && (seq->elements[0]->uint & 128)) + ret->uint = -1; // all ones + + for(size_t i=0; i<seq->used; i++) { + HParsedToken *t = seq->elements[i]; + assert(t->token_type == TT_UINT); + + ret->uint <<= 8; + ret->uint |= t->uint & 0xFF; + } + + if(signedp) { + ret->token_type = TT_SINT; + ret->sint = ret->uint; + } + + return ret; +} +static const HParsedToken *reshape_bits_unsigned(const HParseResult *p) { + return reshape_bits(p, false); +} +static const HParsedToken *reshape_bits_signed(const HParseResult *p) { + return reshape_bits(p, true); +} + static HCFChoice* desugar_bits(HAllocator *mm__, void *env) { struct bits_env *bits = (struct bits_env*)env; if (0 != bits->length % 8) @@ -46,6 +81,11 @@ static HCFChoice* desugar_bits(HAllocator *mm__, void *env) { ret->seq[1] = NULL; ret->action = NULL; + if(bits->signedp) + ret->reshape = reshape_bits_signed; + else + ret->reshape = reshape_bits_unsigned; + return ret; } diff --git a/src/t_parser.c b/src/t_parser.c index 13c4bdf7d980ca8c976c421cd87c0984d11beced..6c4b62a990eff2c89be58426f089eab6bb9c0e06 100644 --- a/src/t_parser.c +++ b/src/t_parser.c @@ -41,6 +41,13 @@ static void test_int32(void) { g_check_parse_failed(int32_, "\xff\xfe\x00", 3); } +static void test_int32_pos(void) { + const HParser *int32_ = h_int32(); + + g_check_parse_ok(int32_, "\x00\x02\x00\x00", 4, "s0x20000"); + g_check_parse_failed(int32_, "\x00\x02\x00", 3); +} + static void test_int16(void) { const HParser *int16_ = h_int16(); @@ -48,6 +55,13 @@ static void test_int16(void) { g_check_parse_failed(int16_, "\xfe", 1); } +static void test_int16_pos(void) { + const HParser *int16_ = h_int16(); + + g_check_parse_ok(int16_, "\x02\x00", 2, "s0x200"); + g_check_parse_failed(int16_, "\x02", 1); +} + static void test_int8(void) { const HParser *int8_ = h_int8(); @@ -395,7 +409,9 @@ void register_parser_tests(void) { g_test_add_func("/core/parser/ch_range", test_ch_range); g_test_add_func("/core/parser/int64", test_int64); g_test_add_func("/core/parser/int32", test_int32); + g_test_add_func("/core/parser/int32_pos", test_int32_pos); g_test_add_func("/core/parser/int16", test_int16); + g_test_add_func("/core/parser/int16_pos", test_int16_pos); g_test_add_func("/core/parser/int8", test_int8); g_test_add_func("/core/parser/uint64", test_uint64); g_test_add_func("/core/parser/uint32", test_uint32);