tttm

git clone https://orangeshoelaces.net/git/tttm.git

5b62d218b3fac5d2ac03ec145a2227d0804ebbda

Author: Vasily Kolobkov on 05/21/2016

Committer: Vasily Kolobkov on 05/21/2016

Dig capabilities whenever present in result response

Refactor parse tree selection into a) selecting from a given root
and b) selecting descendants of one.

Stats

imap.c   | 25 ++--
parser.c | 45 +++++---
parser.h |  1 +
3 files changed, 46 insertions(+), 25 deletions(-)

Patch

diff --git a/imap.c b/imap.c
index 61db883..3955c05 100644
--- a/imap.c
+++ b/imap.c
@@ -27,7 +27,7 @@ static int imap_digcapdata(struct imapctx *, union parnode *);
 static int imap_digunsol(struct imapctx *);
 static int imap_readln(struct imapctx *);
 static int imap_pollres(struct imapctx *);
-static int par2res(union parnode *);
+static int state2res(union parnode *);
 static int str2cap(struct capmap *, char *, size_t);
 static int isprod(union parnode *, int);
 static int islit(union parnode *, int);
@@ -156,7 +156,7 @@ imap_begreeted(struct imapctx *con)
 		goto eproto;
 	}
 
-	if ((n = par_sel(n, n->inter.prod, IP_RESPTXTCODE, IP_CAPDATA, -1)))
+	if ((n = par_seld(n, IP_RESPTXTCODE, IP_CAPDATA, -1)))
 		e = imap_digcapdata(con, n);
 
  exit:
@@ -176,7 +176,7 @@ imap_digcapdata(struct imapctx *con, union parnode *n)
 	for (nend = n + n->inter.len + 1, n++; n < nend; n = par_nn(n)) {
 		if (!isprod(n, IP_CAP))
 			continue;
-		atom = par_sel(n, IP_CAP, IP_ATOM, -1);
+		atom = par_seld(n, IP_ATOM, -1);
 		str = con->rep + (atom + 1)->str.off;
 		len = (atom + 1)->str.len;
 		if (islit(n + 1, IL_AUTHEQ)) {
@@ -212,28 +212,31 @@ int
 imap_pollres(struct imapctx *con)
 {
 	int e;
+	union parnode *s, *c;
 
 	while (!(e = imap_readln(con))) {
-		if (isprod(con->par, IP_TAGGEDRESP)) {
-			e = par2res(con->par);
+		if ((s = par_sel(con->par, IP_TAGGEDRESP, IP_RESPSTATE, -1))) {
+			if ((c = par_seld(s, IP_RESPTXTCODE, IP_CAPDATA, -1))) {
+				e = imap_digcapdata(con, c);
+			}
+			if (!e) {
+				e = state2res(s);
+			}
 			break;
 		}
 		if ((e = imap_digunsol(con)))
-			goto exit;
+			break;
 	}
- exit:
 	return e;
 }
 
 int
-par2res(union parnode *resp)
+state2res(union parnode *respstate)
 {
 	int e;
-	union parnode *s;
 
 	e = TE_OK;
-	s = par_sel(resp, IP_TAGGEDRESP, IP_RESPSTATE, -1);
-	switch ((s + 1)->lit.val) {
+	switch ((respstate + 1)->lit.val) {
 	case IL_NO:
 		e = TE_NO;
 		break;
diff --git a/parser.c b/parser.c
index 2d62847..a2c4e27 100644
--- a/parser.c
+++ b/parser.c
@@ -157,6 +157,7 @@ struct parctx {
 
 typedef int parfn(struct parctx *);
 
+static union parnode * par_seldlist(union parnode *, va_list);
 static int cmpchr(const void *, const void *);
 static int contains(const char *, size_t, char);
 
@@ -331,27 +332,47 @@ union parnode *
 par_sel(union parnode *n, ...)
 {
 	int prod;
-	union parnode *beg, *end;
 	va_list ap;
 
-	beg = n;
 	va_start(ap, n);
-	if ((prod = va_arg(ap, int)) == -1)
-		goto exit;
-	if (n->type == PN_INTER && n->inter.prod == prod) {
+	prod = va_arg(ap, int);
+	if (prod != -1 && n->type == PN_INTER && n->inter.prod == prod) {
+		n = par_seldlist(n, ap);
+	} else {
+		n = 0;
+	}
+	va_end(ap);
+	return n;
+}
+
+union parnode *
+par_seld(union parnode *n, ...)
+{
+	va_list ap;
+
+	va_start(ap, n);
+	n = par_seldlist(n, ap);
+	va_end(ap);
+	return n;
+}
+
+union parnode *
+par_seldlist(union parnode *n, va_list ap)
+{
+	int prod;
+	union parnode *end;
+
+	if (n->type == PN_INTER) {
 		end = n + n->inter.len + 1;
-		n++;
 	} else {
 		n = 0;
 		goto exit;
 	}
 
 	while ((prod = va_arg(ap, int)) != -1) {
-		for (; n < end; n = par_nn(n)) {
-			if (n->type == PN_INTER && n->inter.prod == prod) {
-				n++;
+		for (n++; n < end; n = par_nn(n)) {
+			if (n->type == PN_INTER && n->inter.prod == prod)
 				break;
-			}
 		}
 		if (n == end) {
 			n = 0;
@@ -359,10 +380,6 @@ par_sel(union parnode *n, ...)
 		}
 	}
  exit:
-	if (n != 0 && n != beg)
-		n--;
-
-	va_end(ap);
 	return n;
 }
 
diff --git a/parser.h b/parser.h
index 3295245..9645553 100644
--- a/parser.h
+++ b/parser.h
@@ -57,3 +57,4 @@ struct laxsrc;
 int	par_readln(struct laxsrc *, char *, size_t, int, union parnode *, size_t);
 union parnode *par_nn(union parnode *);
 union parnode *par_sel(union parnode *, ...);
+union parnode *par_seld(union parnode *, ...);