static
int get_token(void)
{
    int token;

    if (ungotten_token != -1)
    {
        token = ungotten_token;
        ungotten_token = -1;
    }
    else
      {
      if (!(token = (ratslexer.yylex)() )) {
            return 0;
      }
      if (accumulators != (accumulator_t *)NULL)
	accumulate_text(accumulators, *ratslexer.yytext);
    }

    switch (token)
    {
        case '(': depths[DEPTH_PARENTHESIS]++;  break;
        case ')': depths[DEPTH_PARENTHESIS]--;  break;
        case '[': depths[DEPTH_BRACKET]++;  break;
        case ']': depths[DEPTH_BRACKET]--;  break;
        case '{': depths[DEPTH_BRACE]++;  break;
        case '}': depths[DEPTH_BRACE]--;  break;
    }

    return token;
}
static
void push_accumulator(char **text)
{
    accumulator_t * acc;

    acc = (accumulator_t *)calloc(sizeof(accumulator_t),1);
    acc->text    = text;
    acc->length  = (*text == (char *)NULL ? 0 : strlen(*text));
    acc->next    = accumulators;
    accumulators = acc;

    accumulate_text(acc, *ratslexer.yytext);
}
static int insert_mime_part_body(struct http_request *hr, char *buf, size_t len)
{
  httpd_request *r = (httpd_request *) hr;
  if (r->u.insert.current_part == PART_AUTHOR) {
    accumulate_text(r, PART_AUTHOR,
		    r->u.insert.author_hex,
		    sizeof r->u.insert.author_hex,
		    &r->u.insert.author_hex_len,
		    buf, len);
  }
  else if (r->u.insert.current_part == PART_SECRET) {
    accumulate_text(r, PART_SECRET,
		    r->u.insert.secret_hex,
		    sizeof r->u.insert.secret_hex,
		    &r->u.insert.secret_hex_len,
		    buf, len);
  }
  else if (r->u.insert.current_part == PART_MANIFEST) {
    form_buf_malloc_accumulate(r, PART_MANIFEST, &r->u.insert.manifest, buf, len);
  }
  else if (r->u.insert.current_part == PART_PAYLOAD) {
    r->u.insert.payload_size += len;
    switch (r->u.insert.payload_status) {
      case RHIZOME_PAYLOAD_STATUS_NEW:
	if (rhizome_write_buffer(&r->u.insert.write, (unsigned char *)buf, len) == -1)
	  return 500;
	break;
      case RHIZOME_PAYLOAD_STATUS_STORED:
	// TODO: calculate payload hash so it can be compared with stored payload
	break;
      default:
	break;
    }
  } else
    FATALF("current_part = %s", alloca_str_toprint(r->u.insert.current_part));
  return 0;
}
static
void pop_accumulator(void)
{
    accumulator_t * acc;

    acc = accumulators;
    accumulators = acc->next;
    if (*(acc->text) != (char *)NULL)
    {
        if (accumulators != (accumulator_t *)NULL)
        {
            accumulators->length = 0;
            accumulate_text(accumulators, *(acc->text));
        }
        acc->length -= strlen(*ratslexer.yytext);
        *(*acc->text + acc->length) = '\0';
    }
    free(acc);
}