#include "token822.h"
#include "parse.h"

static stralloc address = {0};
static token822_alloc tokaddr = {0};

int parse_flagalias;
stralloc parse_alias = {0};
stralloc parse_recips = {0};

stralloc parse_defaulthost = {0};
stralloc parse_defaultdomain = {0};
stralloc parse_plusdomain = {0};

static int gotaddr()
{
 int i;
 int j;
 int flaghasat;

 token822_reverse(&tokaddr);

 flaghasat = 0;
 for (i = 0;i < tokaddr.len;++i)
   if (tokaddr.t[i].type == TOKEN822_AT)
     flaghasat = 1;

 if (token822_unquote(&address,&tokaddr) != 1) return 0;

 if (address.len)
  {
   if (!flaghasat)
    {
     if (!stralloc_cats(&address,"@")) return 0;
     if (!stralloc_cat(&address,&parse_defaulthost)) return 0;
    }
   if (address.s[address.len - 1] == '+')
    {
     address.s[address.len - 1] = '.';
     if (!stralloc_cat(&address,&parse_plusdomain)) return 0;
    }
   j = 0;
   for (i = 0;i < address.len;++i) if (address.s[i] == '@') j = i;
   for (i = j;i < address.len;++i) if (address.s[i] == '.') break;
   if (i == address.len)
    {
     if (!stralloc_cats(&address,".")) return 0;
     if (!stralloc_cat(&address,&parse_defaultdomain)) return 0;
    }
  }

 if (parse_flagalias)
  {
   if (!stralloc_cats(&parse_recips,"R")) return 0;
   if (!stralloc_cat(&parse_recips,&parse_alias)) return 0;
   if (!stralloc_0(&parse_recips)) return 0;
  }

 if (!stralloc_copy(&parse_alias,&address)) return 0;
 parse_flagalias = 1;

 tokaddr.len = 0;
 return 1;
}

static int gotincl()
{
 token822_reverse(&tokaddr);
 if (token822_unquote(&address,&tokaddr) != 1) return 0;

 if (!stralloc_cats(&parse_recips,"I")) return 0;
 if (!stralloc_cat(&parse_recips,&address)) return 0;
 if (!stralloc_0(&parse_recips)) return 0;

 tokaddr.len = 0;
 return 1;
}

int parse(toks)
token822_alloc *toks;
{
 int wordok;
 struct token822 *t;
 struct token822 *beginning;

 wordok = 1;

 tokaddr.len = 0;
 if (!token822_readyplus(&tokaddr,1)) return 0;

 parse_flagalias = 0;
 if (!stralloc_copys(&parse_alias,"")) return 0;
 if (!stralloc_copys(&parse_recips,"")) return 0;

 beginning = toks->t;
 t = toks->t + toks->len;

 while (t > beginning)
   switch((--t)->type)
    {
     case TOKEN822_SEMI:
       break; /*XXX*/
     case TOKEN822_COLON:
       if (t >= beginning + 2)
         if (t[-2].type == TOKEN822_COLON)
	   if (t[-1].type == TOKEN822_ATOM)
	     if (t[-1].slen == 7)
	       if (!byte_diff(t[-1].s,7,"include"))
		{
		 if (!gotincl()) return 0;
                 t -= 2;
		}
       break; /*XXX*/
     case TOKEN822_RIGHT:
       if (tokaddr.len) if (!gotaddr()) return 0;
       while ((t > beginning) && (t[-1].type != TOKEN822_LEFT))
	 if (!token822_append(&tokaddr,--t)) return 0;
       if (!gotaddr()) return 0;
       if (t <= beginning) return -1;
       --t;
       while ((t > beginning) && ((t[-1].type == TOKEN822_COMMENT) || (t[-1].type == TOKEN822_ATOM) || (t[-1].type == TOKEN822_QUOTE) || (t[-1].type == TOKEN822_AT) || (t[-1].type == TOKEN822_DOT)))
	 --t;
       wordok = 0;
       continue;
     case TOKEN822_ATOM: case TOKEN822_QUOTE: case TOKEN822_LITERAL:
       if (!wordok) if (tokaddr.len) if (!gotaddr()) return 0;
       wordok = 0;
       if (!token822_append(&tokaddr,t)) return 0;
       continue;
     case TOKEN822_COMMENT:
       /* comment is lexically a space; shouldn't affect wordok */
       break;
     case TOKEN822_COMMA:
       if (tokaddr.len) if (!gotaddr()) return 0;
       wordok = 1;
       break;
     default:
       wordok = 1;
       if (!token822_append(&tokaddr,t)) return 0;
       continue;
    }
 if (tokaddr.len) if (!gotaddr()) return 0;
 return 1;
}
