/*
islappnd.c - append two stages - Copyright (c) 1995 John T. Grieggs

This program expects two Imagine 3.0 stages, produced by ISL, and makes
a third stage containing both.  This is not entirely trivial, and you
may get wierd effects.  Think about what you're doing here.  What do you
expect multiple SIZE chunks on GLOBALS to do?  If things don't work quite
the way you expect, your resulting stage may require tweaking.  I highly
recommend scoping out each stage before combining them, and making sure
all the paths are what you intend.

islappnd.c is pretty darned brute force, and riddled with assumptions.  If
the format isn't just what ISL produces, or if you use chunks I didn't think
you'd use, it'll break.  That's why you get the source.  :-)

It's actually not a bad example of ISL programming, tho.  Feel free to
grab the unregistered version of ISL from ftp.netcom.com, in the
pub/gr/grieggs/ISL directory.  Be warned that the unregistered version
will not handle EFFECT clauses.

I'll put compiled versions of this program for the Amiga and the PC
in the same directory when I get around to it.

You are welcome to hack this to your hearts content, but may not sell it or
bundle it with any product without specific permission from me.  You may,
however, freely distribute the original source to BBSes, ftp sites, and
online services.  You may distribute modified versions as long as my
comments remain intact and you clearly comment your modifications.

Cheapo manual:

	Copy staging file from first project to staging.1
	Copy staging file from second project to staging.2

	destage staging.1 stage.1
	destage staging.2 stage.2
	islappnd stage.1 stage.2 stage.3
	restage stage.3 staging.3

	If no errors, copy staging.3 to new project directory

Happy rendering!

grieggs@netcom.com

*/

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

#define MAXBUF 200

FILE *fin1, *fin2, *fout;
char inbuf[MAXBUF], outbuf[MAXBUF];
char inbuf1[MAXBUF], inbuf2[MAXBUF];
char *p;
int start, finish;
int max1, max2;

main(int argc, char *argv[])
{
	/* check args */
	if (argc != 4) {
		fprintf(stderr, "Usage: islappnd instage1 instage2 outstage\n");
		exit(1);
	}

	/* open files */
	fin1 = fopen(argv[1], "r");
	if (fin1 == NULL) {
		fprintf(stderr, "Unable to open %s for input\n", argv[1]);
		exit(1);
	}
	fin2 = fopen(argv[2], "r");
	if (fin2 == NULL) {
		fprintf(stderr, "Unable to open %s for input\n", argv[2]);
		exit(1);
	}
	fout = fopen(argv[3], "w");
	if (fout == NULL) {
		fprintf(stderr, "Unable to open %s for output\n", argv[3]);
		exit(1);
	}

	/* get maxframes from first file */
	fgets(inbuf, MAXBUF, fin1);
	fgets(inbuf, MAXBUF, fin1);
	if (!strncmp(inbuf, "MAXFRAMES", strlen("MAXFRAMES"))) {
		p = strstr(inbuf, " ");
		p++;
		max1 = atoi(p);
	}
	fgets(inbuf, MAXBUF, fin1);
	fgets(inbuf, MAXBUF, fin1);

	/* get maxframes from second file */
	fgets(inbuf, MAXBUF, fin2);
	fgets(inbuf, MAXBUF, fin2);
	if (!strncmp(inbuf, "MAXFRAMES", strlen("MAXFRAMES"))) {
		p = strstr(inbuf, " ");
		p++;
		max2 = atoi(p);
	}
	fgets(inbuf, MAXBUF, fin2);
	fgets(inbuf, MAXBUF, fin2);

	/* write header lines, forcing LOOP off */
	fprintf(fout, "STAGE\nMAXFRAMES %d\nLOOP 0\n\n", max1 + max2);

	/* process CAMERAs - this is where it gets gnarly */
	fgets(inbuf, MAXBUF, fin1);
	/* make sure you have CAMERA line from first file */
	if (strncmp(inbuf, "CAMERA", strlen("CAMERA"))) {
		fprintf(stderr, "bad CAMERA\n");
		exit(1);
	}
	fputs(inbuf, fout);
	/* write it - this means all CAMERAs will share a LAYER */
	fgets(inbuf, MAXBUF, fin2);
	/* make sure you have CAMERA line from second file */
	if (strncmp(inbuf, "CAMERA", strlen("CAMERA"))) {
		fprintf(stderr, "bad CAMERA\n");
		exit(1);
	}

	/* We're handling POSITION, ALIGN, and SIZE clauses from each file
	   here, but not ASSOCs or EFFECTs.  Yeah, yeah, it's tacky.  Feel free
	   to write your own.  :-)  EFFECTs would be particularly nasty, as
	   they can span multiple lines.  Still, this will handle any stage
	   I've seen to date - just not every stage allowed by the grammar. */

	/* prime the pump */
	fgets(inbuf1, MAXBUF, fin1);
	fgets(inbuf2, MAXBUF, fin2);

	/* POSITION clauses */
	for (;;) {
		if (strncmp(inbuf1, "POSITION", strlen("POSITION")))
			break;
		fputs(inbuf1, fout);
		fgets(inbuf1, MAXBUF, fin1);
	}
	for (;;) {
		if (strncmp(inbuf2, "POSITION", strlen("POSITION")))
			break;
		/* find key string */
		p = strstr(inbuf2, " FRAMES ");
		if (p == NULL) {
			fputs(inbuf2, fout);
			continue;
		}
		p += strlen(" FRAMES ");
		/* get start frame */
		start = atoi(p);
		/* write first part of line */
		*p++ = '\0';
		fputs(inbuf2, fout);
		/* write shifted start frame */
		fprintf(fout, "%d ", start + max1);
		/* get end frame */
		p = strchr(p, ' ');
		p++;
		finish = atoi(p);
		/* write shifted end frame */
		fprintf(fout, "%d ", finish + max1);
		/* write rest of line */
		p = strchr(p, ' ');
		p++;
		fputs(p, fout);
		fgets(inbuf2, MAXBUF, fin2);
	}

	/* ALIGN clauses */
	for (;;) {
		if (strncmp(inbuf1, "ALIGN", strlen("ALIGN")))
			break;
		fputs(inbuf1, fout);
		fgets(inbuf1, MAXBUF, fin1);
	}
	for (;;) {
		if (strncmp(inbuf2, "ALIGN", strlen("ALIGN")))
			break;
		/* find key string */
		p = strstr(inbuf2, " FRAMES ");
		if (p == NULL) {
			fputs(inbuf2, fout);
			continue;
		}
		p += strlen(" FRAMES ");
		/* get start frame */
		start = atoi(p);
		/* write first part of line */
		*p++ = '\0';
		fputs(inbuf2, fout);
		/* write shifted start frame */
		fprintf(fout, "%d ", start + max1);
		/* get end frame */
		p = strchr(p, ' ');
		p++;
		finish = atoi(p);
		/* write shifted end frame */
		fprintf(fout, "%d ", finish + max1);
		/* write rest of line */
		p = strchr(p, ' ');
		p++;
		fputs(p, fout);
		fgets(inbuf2, MAXBUF, fin2);
	}

	/* SIZE clauses */
	for (;;) {
		if (strncmp(inbuf1, "SIZE", strlen("SIZE")))
			break;
		fputs(inbuf1, fout);
		fgets(inbuf1, MAXBUF, fin1);
	}
	for (;;) {
		if (strncmp(inbuf2, "SIZE", strlen("SIZE")))
			break;
		/* find key string */
		p = strstr(inbuf2, " FRAMES ");
		if (p == NULL) {
			fputs(inbuf2, fout);
			continue;
		}
		p += strlen(" FRAMES ");
		/* get start frame */
		start = atoi(p);
		/* write first part of line */
		*p++ = '\0';
		fputs(inbuf2, fout);
		/* write shifted start frame */
		fprintf(fout, "%d ", start + max1);
		/* get end frame */
		p = strchr(p, ' ');
		p++;
		finish = atoi(p);
		/* write shifted end frame */
		fprintf(fout, "%d ", finish + max1);
		/* write rest of line */
		p = strchr(p, ' ');
		p++;
		fputs(p, fout);
		fgets(inbuf2, MAXBUF, fin2);
	}

	fprintf(fout, "\n");

	/* process GLOBALSs */
	fgets(inbuf, MAXBUF, fin1);
	/* make sure you have GLOBALS line from first file */
	if (strncmp(inbuf, "GLOBALS", strlen("GLOBALS"))) {
		fprintf(stderr, "bad GLOBALS\n");
		exit(1);
	}
	fputs(inbuf, fout);
	/* write it - this means all GLOBALSs will share a LAYER */
	fgets(inbuf, MAXBUF, fin2);
	/* make sure you have GLOBALS line from second file */
	if (strncmp(inbuf, "GLOBALS", strlen("GLOBALS"))) {
		fprintf(stderr, "bad GLOBALS\n");
		exit(1);
	}

	/* We're handling ACTOR and SIZE clauses here.  Note that the
	   grammar allows additional clauses. */

	/* prime the pump */
	fgets(inbuf1, MAXBUF, fin1);
	fgets(inbuf2, MAXBUF, fin2);

	/* ACTOR clauses - hard-wired to 5 lines per! */
	for (;;) {
		if (strncmp(inbuf1, "ACTOR", strlen("ACTOR")))
			break;
		fputs(inbuf1, fout);
		fgets(inbuf1, MAXBUF, fin1);
		fputs(inbuf1, fout);
		fgets(inbuf1, MAXBUF, fin1);
		fputs(inbuf1, fout);
		fgets(inbuf1, MAXBUF, fin1);
		fputs(inbuf1, fout);
		fgets(inbuf1, MAXBUF, fin1);
		fputs(inbuf1, fout);
		fgets(inbuf1, MAXBUF, fin1);
	}
	for (;;) {
		if (strncmp(inbuf2, "ACTOR", strlen("ACTOR")))
			break;
		/* find key string */
		p = strstr(inbuf2, " FRAMES ");
		if (p == NULL) {
			fputs(inbuf2, fout);
			continue;
		}
		p += strlen(" FRAMES ");
		/* get start frame */
		start = atoi(p);
		/* write first part of line */
		*p++ = '\0';
		fputs(inbuf2, fout);
		/* write shifted start frame */
		fprintf(fout, "%d ", start + max1);
		/* get end frame */
		p = strchr(p, ' ');
		p++;
		finish = atoi(p);
		/* write shifted end frame */
		fprintf(fout, "%d ", finish + max1);
		/* write rest of line */
		p = strchr(p, ' ');
		p++;
		fputs(p, fout);
		fgets(inbuf2, MAXBUF, fin2);
		fputs(inbuf2, fout);
		fgets(inbuf2, MAXBUF, fin2);
		fputs(inbuf2, fout);
		fgets(inbuf2, MAXBUF, fin2);
		fputs(inbuf2, fout);
		fgets(inbuf2, MAXBUF, fin2);
		fputs(inbuf2, fout);
		fgets(inbuf2, MAXBUF, fin2);
	}

	/* SIZE clauses */
	for (;;) {
		if (strncmp(inbuf1, "SIZE", strlen("SIZE")))
			break;
		fputs(inbuf1, fout);
		fgets(inbuf1, MAXBUF, fin1);
	}
	for (;;) {
		if (strncmp(inbuf2, "SIZE", strlen("SIZE")))
			break;
		/* find key string */
		p = strstr(inbuf2, " FRAMES ");
		if (p == NULL) {
			fputs(inbuf2, fout);
			continue;
		}
		p += strlen(" FRAMES ");
		/* get start frame */
		start = atoi(p);
		/* write first part of line */
		*p++ = '\0';
		fputs(inbuf2, fout);
		/* write shifted start frame */
		fprintf(fout, "%d ", start + max1);
		/* get end frame */
		p = strchr(p, ' ');
		p++;
		finish = atoi(p);
		/* write shifted end frame */
		fprintf(fout, "%d ", finish + max1);
		/* write rest of line */
		p = strchr(p, ' ');
		p++;
		fputs(p, fout);
		fgets(inbuf2, MAXBUF, fin2);
	}

	fprintf(fout, "\n");

	/* process rest of first file */
	for (;;) {
		/* get a line */
		fgets(inbuf, MAXBUF, fin1);
		if (feof(fin1))
			break;
		/* echo it to the output file */
		fputs(inbuf, fout);
	}

	/* process rest of second file */
	for (;;) {
		/* get a line */
		fgets(inbuf, MAXBUF, fin2);
		if (feof(fin2))
			break;
		/* find key string */
		p = strstr(inbuf, " FRAMES ");
		if (p == NULL) {
			fputs(inbuf, fout);
			continue;
		}
		p += strlen(" FRAMES ");
		/* get start frame */
		start = atoi(p);
		/* write first part of line */
		*p++ = '\0';
		fputs(inbuf, fout);
		/* write shifted start frame */
		fprintf(fout, "%d ", start + max1);
		/* get end frame */
		p = strchr(p, ' ');
		p++;
		finish = atoi(p);
		/* write shifted end frame */
		fprintf(fout, "%d ", finish + max1);
		/* write rest of line */
		p = strchr(p, ' ');
		p++;
		fputs(p, fout);
	}

	/* clean up */
	fclose(fin1);
	fclose(fin2);
	fclose(fout);
}

