diff --git a/pdf.c b/pdf.c index f09e564676fa73a774aa8e6df291b4b5fcfd5e84..ad5579c8fd8d81b1ca2cf62f5488beba0ef67f26 100644 --- a/pdf.c +++ b/pdf.c @@ -222,6 +222,31 @@ act_hupper(const HParseResult *p, void *u) return H_MAKE_UINT(H_CAST_UINT(p->ast) - 'A'); } +HParsedToken* +act_hdigitpair(const HParseResult *p, void *u) +{ + uint8_t b = 0; + HCountedArray *seq = H_CAST_SEQ(p->ast); + size_t digits_processed = 0; + uint8_t digits[2]; + for(size_t i = 0; i < seq->used; ++i) + { + switch(seq->elements[i]->token_type) + { + case TT_UINT: + digits[digits_processed] = H_CAST_UINT(seq->elements[i]); + digits_processed++; + break; + default: + break; + } + assert(digits_processed == 2); + } + + b = (digits[0] << 4) + digits[1]; + return H_MAKE_UINT(b); +} + HParsedToken * act_ahextruncated(const HParseResult *p, void *u) { @@ -237,6 +262,46 @@ act_ahextruncated(const HParseResult *p, void *u) return H_MAKE_UINT(b); } +HParsedToken * +act_hs_end(const HParseResult *p, void *u) +{ + HParsedToken *res; + HCountedArray *seq = H_CAST_SEQ(p->ast); + assert(seq->used >= 1); + + res = H_MAKE_UINT(H_CAST_UINT(seq->elements[0])); + return res; +} + +HParsedToken * +act_ahexstream(const HParseResult *p, void *u) +{ + uint8_t *result_bytes; + size_t chunk_number; + size_t required_bytes; + size_t out_pos = 0; + HCountedArray *seq = H_CAST_SEQ(p->ast); + HParsedToken *res; + + /* Ignore the the last element, which is EOD */ + required_bytes = (seq->used - 1) * 8; + + result_bytes = h_arena_malloc(p->arena, required_bytes); + + /* memcpy all but the last group's bytes into a single array */ + for (size_t i = 0; i < seq->used-1; ++i) + { + assert(i * 8 < required_bytes); + result_bytes[i] = H_CAST_UINT(seq->elements[i]); + } + + /* We should have filled the array exactly by this point */ + + res = H_MAKE_BYTES(result_bytes, required_bytes); + return res; +} + + HParsedToken * act_a85zero(const HParseResult *p, void *u) { @@ -912,11 +977,11 @@ init_parser(struct Env *aux) /* AsciiHexDecode parser */ H_RULE(ahexeod, h_ch('>')); - H_RULE(hdigitpair, SEQ(IGN(OPT(h_many(lwchar))), hdigit, IGN(OPT(h_many(lwchar))), hdigit)); - H_ARULE(ahextruncated, SEQ(IGN(OPT(h_many(lwchar))), hdigit, IGN(OPT(h_many(lwchar))), ahexeod)); + H_ARULE(hdigitpair, SEQ(IGN(OPT(h_many(lwchar))), hdigit, IGN(OPT(h_many(lwchar))), hdigit)); + H_ARULE(ahextruncated, SEQ(IGN(OPT(h_many(lwchar))), hdigit, IGN(OPT(h_many(lwchar))))); - H_RULE(hs_end, CHX(hdigitpair, ahextruncated)); - H_RULE(hexstream, SEQ(h_many(hdigitpair), hs_end)); + H_ARULE(hs_end, SEQ(CHX(hdigitpair, ahextruncated), ahexeod)); + H_ARULE(ahexstream, SEQ(h_many(hdigitpair), hs_end)); /* global parser variables */ @@ -926,7 +991,7 @@ init_parser(struct Env *aux) p_xref = CHX(xr_td, xrstm); p_objdef = objdef; p_a85string = a85string; - p_ahexstream = hexstream; + p_ahexstream = ahexstream; p_fail = h_nothing_p(); p_epsilon = epsilon;