/*	This code uses GCC's 64-bit long long int support.
*/

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>

#define	BLOCKSIZE	4096

typedef struct {int key, datum; } item;
item a[BLOCKSIZE];

void
binary(register long long maxsort)
{
	/* Read ascii integer pairs and output binary form */
	register long long t = 0;
	register int i = 0;

	while (t < maxsort) {
		if (scanf("%d%d", &(a[i].key), &(a[i].datum)) != 2) {
			fprintf(stderr,
				"Error: only %lld of %lld items on input\n",
				t,
				maxsort);
			exit(2);
		}
		++t;
		++i;
		if (i == BLOCKSIZE) {
			write(1, a, sizeof(a));
			i = 0;
		}
	}

	if (i > 0) {
		write(1, a, (i * sizeof(a[0])));
	}
}

void
check(register long long maxsort)
{
	register long long t = maxsort;
	register int max = 0x80000000;
	register int i;

	while (t > 0) {
		register int j = BLOCKSIZE;
		register int k;

		if (j > t) j = t;
		k = read(0, a, (j * sizeof(a[0])));
		if (k != (j * sizeof(a[0]))) {
			fprintf(stderr,
				"Error: only %lld of %lld items on input\n",
				((maxsort - t) + (k / sizeof(a[0]))),
				maxsort);
			exit(2);
		}
		for (i=0; i<j; ++i) {
			register int new = a[i].key;
			if (new < max) {
				fprintf(stderr,
					"Error: item %lld is out of order\n",
					((maxsort - t) + i));
				exit(3);
			}
			max = new;
		}
		t -= j;
	}
}

inline int
myrand(void)
{
	/* Generate a 32-bit random number using random()...
	   random() usually generates only 31-bit values
	*/
	register int a = random();
	register int b = random();
	register int c = random();

	return(a ^ (b << ((c & 15) + 1)));
}

void
generate(register long long maxsort)
{
	register int datum = 0;
	register int i = 0;

	while (maxsort > 0) {
		--maxsort;
		a[i].key = myrand();
		a[i].datum = datum;
		++datum;
		++i;
		if (i == BLOCKSIZE) {
			write(1, a, sizeof(a));
			i = 0;
		}
	}

	if (i > 0) {
		write(1, a, (i * sizeof(a[0])));
	}
}

void
view(register long long maxsort)
{
	register long long t = maxsort;
	register int i;

	while (t > 0) {
		register int j = BLOCKSIZE;
		register int k;

		if (j > t) j = t;
		k = read(0, a, (j * sizeof(a[0])));
		if (k != (j * sizeof(a[0]))) {
			fprintf(stderr,
				"Error: only %lld of %lld items on input\n",
				((maxsort - t) + (k / sizeof(a[0]))),
				maxsort);
			exit(2);
		}
		for (i=0; i<j; ++i) {
			printf("%d %d\n", a[i].key, a[i].datum);
		}
		t -= j;
	}
}

int
main(register int argc,
register char **argv)
{
	long long maxsort;

	if (((argc != 2) && (argc != 3)) ||
	    (sscanf(argv[1], "%lld", &maxsort) != 1) ||
	    (maxsort < 1L)) {
usage:
		fprintf(stderr,
			"Usage:\n"
			"binary [maxsort]\n"
			"check [maxsort]\n"
			"generate [maxsort] {seed}\n"
			"view [maxsort]\n");
		exit(1);
	}

	switch (*(*argv + (strlen(*argv) - 1))) {
	case 'y':
		/* Run as binary program */
		binary(maxsort);
		break;
	case 'e':
		/* Run as generate program */
		if (argc == 2) {
			srandom(time(0));
		} else {
			srandom(atoi(argv[2]));
		}
		generate(maxsort);
		break;
	case 'k':
		/* Run as check program */
		check(maxsort);
		break;
	case 'w':
		/* Run as view program */
		view(maxsort);
		break;
	default:
		goto usage;
	}

	exit(0);
}
