#include <exec/types.h>
#include <clib/dos_protos.h>
#include <pragmas/dos_lib.h>
#include <stdio.h>

struct ar_file {
	char ar_name[16];
	char ar_date[12];
	char ar_uid[6];
	char ar_gid[6];
	char ar_mode[8];
	char ar_size[10];
	char ar_fmag[2];
};

int
charsinrange(char *buf, int len, char low, char high)
{
	char c;
	while (len) {
		c = *buf++;
		if (c < low || c > high)
			break;
		len--;
	}
	while (len--) {
		if (c != ' ')
			return 0;
		c = *buf++;
	}
	return 1;
}

int
validheader(struct ar_file *h)
{
	if (!charsinrange(h->ar_name, 16, ' ', 127))
		return 0;
	if (!charsinrange(h->ar_date, 12, '0', '9'))
		return 0;
	if (!charsinrange(h->ar_uid, 6, '0', '9'))
		return 0;
	if (!charsinrange(h->ar_gid, 6, '0', '9'))
		return 0;
	if (!charsinrange(h->ar_mode, 8, '0', '7'))
		return 0;
	if (!charsinrange(h->ar_size, 10, '0', '9'))
		return 0;
	return 1;
}

int
unranlib(FILE *in, FILE *out)
{
	char magic[8];
	struct ar_file header;
	long fileoff;
	int c, oldc;
	char rollingbuf[sizeof(header)];
	int i;
	char buf[512];

	if (!fread(magic, sizeof(magic), 1, in)) {
		fprintf(stderr, "Fatal: unexpected EOF reading magic number\n");
		return 0;
	}
	if (memcmp(magic, "!<arch>\n", sizeof(magic))) {
		fprintf(stderr, "Fatal: not an ar(1) archive\n");
		return 0;
	}
	if (!fread(&header, sizeof(header), 1, in)) {
		fprintf(stderr, "Fatal: unexpected EOF reading file header\n");
		return 0;
	}
	if (header.ar_fmag[0] != '`' || header.ar_fmag[1] != '\n') {
		fprintf(stderr, "Fatal: first file is corrupt\n");
		return 0;
	}
	if (memcmp(header.ar_name, "__.SYMDEF       ", 16)) {
		fprintf(stderr, "Fatal: file has no __.SYMDEF index\n");
		return 0;
	}
	i = c = 0;
	for (;;) {
		oldc = c;
		c = getc(in);
		if (c == EOF) {
			fprintf(stderr, "Fatal: unexpected EOF searching for file\n");
			return 0;
		}
		rollingbuf[i++] = c;
		if (i == sizeof(header))
			i = 0;
		if (c == '\n' && oldc == '`') {
			memcpy(&header, rollingbuf+i, sizeof(header)-i);
			memcpy((char *)(&header+1)-i, rollingbuf, i);
			if (validheader(&header))
				break;
		}
	}
/* Okay, we have a valid header = now start copying out */
	if (!fwrite(magic, sizeof(magic), 1, out)) {
		fprintf(stderr, "Fatal: error writing output file");
		return 0;
	}
	if (!fwrite(&header, sizeof(header), 1, out)) {
		fprintf(stderr, "Fatal: error writing output file");
		return 0;
	}
	for (;;) {
		i = fread(buf, 1, sizeof(buf), in);
		if (!i)
			break;
		if (fwrite(buf, 1, i, out) != i) {
			fprintf(stderr, "Fatal: error writing output file");
			return 0;
		}
	}
	if (!feof(in)) {
		fprintf(stderr, "Error reading input file: %d\n", ferror(in));
		return 0;
	}
	return 1;	/* Success */
}

int
main(int argc, char **argv)
{
	char filebuf[512];
	char *p;
	int error;
	FILE *in, *out;

	while (--argc) {
		argv++;
		printf("Removing ranlib information from \"%s\"\n", *argv);
		if (strlen(*argv) > sizeof(filebuf) - 5) {
			fprintf(stderr, "Path \"%s\" too long - skipping\n", *argv);
			continue;
		}
		strcpy(filebuf, *argv);
		strcat(filebuf, ".bak");
		if (!Rename((UBYTE *)*argv, (UBYTE *)filebuf)) {
			fprintf(stderr, "Fatal: unable to rename to \"%s\": DOS Error %d\n", filebuf, IoErr());
			return 10;
		}
		if (!(in = fopen(filebuf, "rb"))) {
			fprintf(stderr, "Fatal: unable to open \"%s\" for input\n", filebuf);
			return 10;
		}
		if (!(out = fopen(*argv, "wb"))) {
			fprintf(stderr, "Fatal: unable to open \"%s\" for input\n", filebuf);
			return 10;
		}
		if (!unranlib(in, out)) {
			return 10;
		}
		if (error = fclose(in)) {
			fprintf(stderr, "Unable to close \"%s\": error %d\n", filebuf, error);
			return 10;
		}
		if (error = fclose(out)) {
			fprintf(stderr, "Unable to close \"%s\": error %d\n", *argv, error);
			return 10;
		}
	}
	printf("All done.\n");
	return 0;
}
