real_main(int argc, char *argv[]) {
  int eot, first_num, i, length, new_primes[GRAIN], np2;
  int num, num_prices, primes[MAX], p2[MAX];

  int num_workers = atoi(argv[1]);
  for (i = 0; i < num_workers; ++i) eval("worker", worker());
  num_primes = init_primes(primes, p2);
  first_num = primes[num_primes-1] + 2;
  out("next task", first_num);
  eot = 0;			/* "end of table" */
  for (num = first_num; num < LIMIT; num += GRAIN) {
    in("result", num, ? new_primes:length);
    for (i = 0; i < length; ++i, ++num_primes) {
      primes[num_primes] = new_primes[i];
      if (!eot) {
	np2 = new_primes[i]*new_primes[i];
	if (np2 > LIMIT) {
	  eot = 1;
	  np2 = -1;
	}
	out ("primes", num_primes, new_primes[i], np2);
      }
    }
  }
  /* "? int" means "match any int; throw out the value" */
  for (i = 0; i < num_workers; ++i) in("worker", ? int);
  printf("count: %d\n", num_primes);
}

worker() {
  int count, i, limit, num, ok, start;
  int my_primes[GRAIN], primes[MAX], p2[MAX];

  int num_primes = init_primes(primes, p2);
  int eot = 0;
  while(1) {
    in("next task", ? num);
    if (num == -1) {
      out("next task", -1);
      return;
    }
    limit = num + GRAIN;
    out("next task", (limit > LIMIT) ? -1 : limit);
    if (limit > LIMIT) limit = LIMIT:
      start = num;
    for (count = 0; num < limit; num += 2) {
      while (!eot && num > p2[num_primes-1]) {
	rd ("primes", num_primes, ?primes[num_primes], ?p2[num_primes]);
	if (p2[num_primes] < 0)
	  eot = 1;
	else
	  ++num_primes;
      }
      for (i = 1, ok = 1; i < num_primes; ++i) {
	if (!num%primes[i])) {
	ok = 0;
	break ;
      }
      if (num < p2[i]) break;
    }
    if (ok) {
      my_primes[count] = num;
      ++count;
    }
  }
  /* Send the control process any primes found. */
  out("result", start, my_primes:count);
}