#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define BUFF_LEN 256

unsigned char read_buff[BUFF_LEN];
unsigned char cmd[BUFF_LEN];
unsigned char *input_batch = "gs_exec.bat";
unsigned char tmp_ps[128];
unsigned char tmp_batch[128];
unsigned char ps_file[128];
int output_page;
int page_spec = -1;
void putdef(FILE *);

void usage(int code)
{
	fputs("gssmerge : Merge output of `gssub'.  ",stderr);
	fputs("Version 0.1  Apr. 1993, K.Asayama\n",stderr);
	fputs("Usage    : gssmerge [-p<page_number>] [batch file]\n",stderr);
	fputs("           default name of batch file is \"gs_exec.bat\".\n",stderr);
	exit(code);
}

int main(int argc,char *argv[])
{
	FILE *fpi,*fpo;
	int i,j,idummy;
	int page;
	long cont_start,cont_end,cur_pos;
	char init_f;
	int cargc;
	char *cargv[20];
	int x_size,y_size;
	unsigned char *OutputFile;
	
	for (i=1;i<argc && *argv[i] == '-';i++) {
		switch(*(argv[i]+1)) {
			case 'h' : usage(0);
			case 'p' :
				page_spec = atoi(argv[i]+2);
				if (page_spec <= 0) usage(1);
				break;
			default :
				fprintf(stderr,"Unknown flag `%s'.\n",argv[i]);
				usage(1);
		}
	}
	if (i+1 == argc) {
		input_batch = argv[i];
	}
	else if (i < argc) {
		fputs("Too many arguments.",stderr);
		usage(1);
	}
	fpi = fopen(input_batch,"r");
	if (fpi == NULL) {
		fprintf(stderr,"Cannot open `%s'.\n",input_batch);
		exit(1);
	}
	
	while (fgets(read_buff,BUFF_LEN,fpi) != NULL) {
		for (i=0;read_buff[i];i++)
			if (!isspace(read_buff[i])) break;
		if (read_buff[i] == '\0') continue;
		if (sscanf(read_buff,"REM Page: %d",&page) != 1) {
batch_incorrect:
			fprintf(stderr,"`%s' seems created by old or incorrect version of gssub.\n",input_batch);
			exit(1);
		}
		fgets(read_buff,BUFF_LEN,fpi);
		if (page_spec >= 0) {
			sprintf(tmp_ps,"p%05d$$.ps",page_spec);
			sprintf(tmp_batch,"gs_%05d.bat",page_spec);
		}
		else if (sscanf(read_buff,"REM %s %d",ps_file,&idummy) == 2) {
			sprintf(tmp_ps,"p%05d$$.ps",page);
			sprintf(tmp_batch,"gs_%05d.bat",page);
		}
		else {
			strcpy(tmp_ps,"pall$$.ps");
			strcpy(tmp_batch,"gs_all.bat");
		}
		cont_start = ftell(fpi);
		cont_end = 0;
		while (fgets(read_buff,BUFF_LEN,fpi) != NULL) {
			if (strncmp(read_buff,"gs ",3) == 0) break;
			if (strncmp(read_buff,"echo ",5) != 0)
				goto batch_incorrect;
			cont_end = ftell(fpi);
		}
		if (page_spec >= 0 && page != page_spec) continue;
		strcpy(cmd,read_buff);
		for (cargc=0,i=0;cmd[i]; ) {
			for ( ;cmd[i];i++)
				if (!isspace(cmd[i])) break;
			cargv[cargc] = cmd+i;
			for ( ;cmd[i];i++)
				if (isspace(cmd[i])) break;
			cmd[i++] = 0;
			
			if (cargc == 0) {
				cargc++; continue;
			}
			if (*cargv[cargc] != '-') break;
			if (*(cargv[cargc]+1) == '-') break;
			if (strncmp("-sOUTPUTFILE=",cargv[cargc],13) == 0) {
				OutputFile = cargv[cargc]+13;
			}
			else if (strncmp("-g",cargv[cargc],2) == 0) {
				if (sscanf(cargv[cargc]+2,"%dx%d",&x_size,&y_size) != 2)
					goto batch_incorrect;
			}
			else cargc++;
		}
		
		fpo = fopen(tmp_ps,"a");
		if (fpo == NULL) {
			fprintf(stderr,"Cannot open `%s'.\n",tmp_ps);
			exit(1);
		}
		fseek(fpo,0,SEEK_END);
		if (ftell(fpo) == 0)
			putdef(fpo);
		fseek(fpi,cont_start,SEEK_SET);
		
		cur_pos = 0;
		fputs("userdict begin\ngsave\n",fpo);
		fprintf(fpo,"[%d %d] (%s) SetDeviceForDviprt\n",
			x_size,y_size,OutputFile);
		while (cur_pos < cont_end) {
			fgets(read_buff,BUFF_LEN,fpi);
			for (i=5;read_buff[i];i++) {
				if (read_buff[i] == '>') break;
				fputc(read_buff[i],fpo);
			}
			fputc('\n',fpo);
			cur_pos = ftell(fpi);
		}
		fputs("grestore\nend\n",fpo);
		fclose(fpo);
		fgets(read_buff,BUFF_LEN,fpi);
		
		fpo = fopen(tmp_batch,"w");
		if (fpo == NULL) {
			fprintf(stderr,"Cannot open `%s'.\n",tmp_batch);
			exit(1);
		}
		for (i=0;i<cargc;i++) {
			fprintf(fpo,"%s ",cargv[i]);
		}
		fprintf(fpo,"-- %s\n",tmp_ps);
		fclose(fpo);
	}
	fclose(fpi);
	return 0;
}

void putdef(FILE *fp)
{
	char *str[] = {
		"userdict begin",
		"  /SetDeviceForDviprt {",
		"  10 dict begin",
		"    /outputfile exch def /size exch def",
		"    currentdevice getdeviceprops",
		"    counttomark dup /PropsCount exch def 2 div cvi {",
		"    1 index /N exch def",
		"      N /HWSize eq {",
		"        pop size",
		"      } {",
		"        N /OutputFile eq {",
		"          pop outputfile",
		"        } if",
		"      } ifelse",
		"      PropsCount 2 roll",
		"    } repeat",
		"  end",
		"  currentdevice putdeviceprops setdevice",
		"  } bind def",
		"end",
		NULL,
	};
	int i;
	
	for (i=0;str[i]!=NULL;i++) {
		fprintf(fp,"%s\n",str[i]);
	}
}
