add helpers for easier token construction and access to sequence elements

This commit is contained in:
Sven M. Hallberg 2013-01-15 20:02:53 +01:00
parent b5db3177db
commit 342e39eb61

View file

@ -11,9 +11,79 @@
#define false 0 #define false 0
#define true 1 #define true 1
///
// API Additions
///
#define H_RULE(rule, def) const HParser *rule = def #define H_RULE(rule, def) const HParser *rule = def
#define H_ARULE(rule, def) const HParser *rule = h_action(def, act_ ## rule) #define H_ARULE(rule, def) const HParser *rule = h_action(def, act_ ## rule)
// The action equivalent of h_ignore.
const HParsedToken *act_ignore(const HParseResult *p)
{
return NULL;
}
// Helper to build HAction's that pick one index out of a sequence.
const HParsedToken *act_index(int i, const HParseResult *p)
{
if(!p) return NULL;
const HParsedToken *tok = p->ast;
if(!tok || tok->token_type != TT_SEQUENCE)
return NULL;
const HCountedArray *seq = tok->seq;
size_t n = seq->used;
if(i<0 || (size_t)i>=n)
return NULL;
else
return tok->seq->elements[i];
}
const HParsedToken *act_index0(const HParseResult *p)
{
return act_index(0, p);
}
HParsedToken *h_make_token(HArena *arena, HTokenType type, void *value) {
HParsedToken *ret = h_arena_malloc(arena, sizeof(HParsedToken));
ret->token_type = type;
ret->user = value;
return ret;
}
#define H_MAKE(TYP) \
((TYP ## _t *) h_arena_malloc(p->arena, sizeof(TYP ## _t)))
#define H_MAKE_TOKEN(TYP, VAL) \
h_make_token(p->arena, TT_ ## TYP, VAL)
HParsedToken *h_carray_index(const HCountedArray *a, size_t i) {
assert(i < a->used);
return a->elements[i];
}
HParsedToken *h_seq_index(const HParsedToken *p, size_t i) {
assert(p->token_type == TT_SEQUENCE);
return h_carray_index(p->seq, i);
}
void *h_seq_index_user(HTokenType type, const HParsedToken *p, size_t i) {
HParsedToken *elem = h_seq_index(p, i);
assert(elem->token_type == (HTokenType)type);
return elem->user;
}
#define H_SEQ_INDEX(TYP, SEQ, IDX) \
((TYP ## _t *) h_seq_index_user(TT_ ## TYP, SEQ, IDX))
#define H_FIELD(TYP, IDX) \
H_SEQ_INDEX(TYP, p->ast, IDX)
bool is_zero(HParseResult *p) { bool is_zero(HParseResult *p) {
if (TT_UINT != p->ast->token_type) if (TT_UINT != p->ast->token_type)
@ -21,6 +91,11 @@ bool is_zero(HParseResult *p) {
return (0 == p->ast->uint); return (0 == p->ast->uint);
} }
///
// Semantic Actions
///
/** /**
* Every DNS message should have QDCOUNT entries in the question * Every DNS message should have QDCOUNT entries in the question
* section, and ANCOUNT+NSCOUNT+ARCOUNT resource records. * section, and ANCOUNT+NSCOUNT+ARCOUNT resource records.
@ -268,10 +343,6 @@ void set_rr(struct dns_rr rr, HCountedArray *rdata) {
} }
const HParsedToken* act_header(const HParseResult *p) { const HParsedToken* act_header(const HParseResult *p) {
HParsedToken *ret = h_arena_malloc(p->arena, sizeof(HParsedToken));
ret->token_type = TT_dns_header;
ret->user = h_arena_malloc(p->arena, sizeof(dns_header_t));
HParsedToken **fields = p->ast->seq->elements; HParsedToken **fields = p->ast->seq->elements;
dns_header_t header_ = { dns_header_t header_ = {
.id = fields[0]->uint, .id = fields[0]->uint,
@ -287,16 +358,15 @@ const HParsedToken* act_header(const HParseResult *p) {
.authority_count = fields[10]->uint, .authority_count = fields[10]->uint,
.additional_count = fields[11]->uint .additional_count = fields[11]->uint
}; };
*(dns_header_t *)ret->user = header_;
return ret; dns_header_t *header = H_MAKE(dns_header);
*header = header_;
return H_MAKE_TOKEN(dns_header, header);
} }
const HParsedToken* act_label(const HParseResult *p) { const HParsedToken* act_label(const HParseResult *p) {
HParsedToken *ret = h_arena_malloc(p->arena, sizeof(HParsedToken)); dns_label_t *r = H_MAKE(dns_label);
ret->token_type = TT_dns_label;
ret->user = h_arena_malloc(p->arena, sizeof(dns_label_t));
dns_label_t *r = (dns_label_t *)ret->user;
r->len = p->ast->seq->used; r->len = p->ast->seq->used;
r->label = h_arena_malloc(p->arena, r->len + 1); r->label = h_arena_malloc(p->arena, r->len + 1);
@ -304,41 +374,31 @@ const HParsedToken* act_label(const HParseResult *p) {
r->label[i] = p->ast->seq->elements[i]->uint; r->label[i] = p->ast->seq->elements[i]->uint;
r->label[r->len] = 0; r->label[r->len] = 0;
return ret; return H_MAKE_TOKEN(dns_label, r);
} }
const HParsedToken* act_question(const HParseResult *p) { const HParsedToken* act_question(const HParseResult *p) {
HParsedToken *ret = h_arena_malloc(p->arena, sizeof(HParsedToken)); dns_question_t *q = H_MAKE(dns_question);
ret->token_type = TT_dns_question;
ret->user = h_arena_malloc(p->arena, sizeof(dns_question_t));
dns_question_t *q = (dns_question_t *)ret->user;
HParsedToken **fields = p->ast->seq->elements; HParsedToken **fields = p->ast->seq->elements;
// QNAME is a sequence of labels. Pack them into an array. // QNAME is a sequence of labels. Pack them into an array.
q->qname.qlen = fields[0]->seq->used; q->qname.qlen = fields[0]->seq->used;
q->qname.labels = h_arena_malloc(p->arena, sizeof(dns_label_t)*q->qname.qlen); q->qname.labels = h_arena_malloc(p->arena, sizeof(dns_label_t)*q->qname.qlen);
for(size_t i=0; i<fields[0]->seq->used; i++) { for(size_t i=0; i<fields[0]->seq->used; i++) {
assert(fields[0]->seq->elements[i]->token_type == (HTokenType)TT_dns_label); q->qname.labels[i] = *H_SEQ_INDEX(dns_label, fields[0], i);
q->qname.labels[i] = *(dns_label_t *)fields[0]->seq->elements[i]->user;
} }
q->qtype = fields[1]->uint; q->qtype = fields[1]->uint;
q->qclass = fields[2]->uint; q->qclass = fields[2]->uint;
return ret; return H_MAKE_TOKEN(dns_question, q);
} }
const HParsedToken* act_message(const HParseResult *p) { const HParsedToken* act_message(const HParseResult *p) {
h_pprint(stdout, p->ast, 0, 2); h_pprint(stdout, p->ast, 0, 2);
dns_message_t *msg = H_MAKE(dns_message);
HParsedToken *ret = h_arena_malloc(p->arena, sizeof(HParsedToken)); dns_header_t *header = H_FIELD(dns_header, 0);
ret->token_type = TT_dns_message;
ret->user = h_arena_malloc(p->arena, sizeof(dns_message_t));
dns_message_t *msg = ret->user;
assert(p->ast->seq->elements[0]->token_type == (HTokenType)TT_dns_header);
dns_header_t *header = (dns_header_t *)p->ast->seq->elements[0]->user;
msg->header = *header; msg->header = *header;
HParsedToken *qs = p->ast->seq->elements[1]; HParsedToken *qs = p->ast->seq->elements[1];
@ -387,42 +447,17 @@ const HParsedToken* act_message(const HParseResult *p) {
} }
msg->additional = additional; msg->additional = additional;
return ret; return H_MAKE_TOKEN(dns_message, msg);
}
// The action equivalent of h_ignore.
const HParsedToken *act_ignore(const HParseResult *p)
{
return NULL;
}
// Helper to build HAction's that pick one index out of a sequence.
const HParsedToken *act_index(int i, const HParseResult *p)
{
if(!p) return NULL;
const HParsedToken *tok = p->ast;
if(!tok || tok->token_type != TT_SEQUENCE)
return NULL;
const HCountedArray *seq = tok->seq;
size_t n = seq->used;
if(i<0 || (size_t)i>=n)
return NULL;
else
return tok->seq->elements[i];
}
const HParsedToken *act_index0(const HParseResult *p)
{
return act_index(0, p);
} }
#define act_hdzero act_ignore #define act_hdzero act_ignore
#define act_qname act_index0 #define act_qname act_index0
///
// Parser / Grammar
///
const HParser* init_parser() { const HParser* init_parser() {
static const HParser *ret = NULL; static const HParser *ret = NULL;
if (ret) if (ret)
@ -476,6 +511,11 @@ const HParser* init_parser() {
return ret; return ret;
} }
///
// Program Logic for a Dummy DNS Server
///
int start_listening() { int start_listening() {
// return: fd // return: fd
int sock; int sock;