/*===========================================================================
  Copyright (C) 1995-2005 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*
 * HEADER : ascii2mf.c     - Vers 3.6.002  - Sep 1993 -  L. Fini, OAA
 *                         - Vers 3.6.001  - Aug 1992 -  L. Fini, OAA
 *
 *
 *  AGL Metafile Conversion
 *
 * This utility program converts an ASCII AGL metafile into a standard AGL
 * metafile. It is the reverse of the MF2ASCII program.
 *
 * AGL standard metafile are byte oriented files containing a standard
 * header (the 21-char. string: "AGL Standard metafile"), followed by AGL
 * instruction codes with related argument values. Arguments are int, float
 * or char values expressed as unformatted binary.
 *
 * AGL ASCII files are character oriented files containing the standard
 * header: "# AGL ASCII metafile" followed by instruction codes (AGL routine
 * names) and related argument values. Int arguments are decimal values
 * (format: %d), float arguments are floating point numbers (format: %e),
 * char arguments are output as such.
 *
 * A full list of AGL instruction codes and related argument formats
 * is reported in the following table:
 *
 *  Routine
 *  Code       Arguments       Description

.VERSION
051021		last modif

 *---------------------------------------------------------------------------
 *  CDEF x1 x2 y1 y2           Define clipping area.
 *
 *  WDEF x1 x2 y1 y2           Define window
 *
 *  ESC  n                     Escape command
 *  0x00 0x11 ... 0xNN         (n bytes)
 *
 *  EXTN n                     Future Extension
 *  0x00 0x11 ... 0xNN         (n bytes)
 *
 *  VERS                       Erase current viewport
 *
 *  GPLL 5                     Polyline for 5  (x,y) couples
 *  x y 
 *  x y
 *  x y
 *  x y
 *  x y
 *
 *  GPLM 7 5                   Polymarker with marker 7 for 5  (x,y) couples
 *  x y
 *  x y
 *  x y
 *  x y
 *  x y
 *
 *  GINT 5                     Polyline for 5  (x,y) couples
 *  x y 
 *  x y
 *  x y
 *  x y
 *  x y
 *
 *  SSET 5                     Set status command="string" (5 chars)
 *  string
 *
 *  GTXT x y 1 3               Write "Str" (3 chars), center 1 in (x,y)
 *  Str
 *
 *  EOF                        End of File
 */

#include <aglenvr.h>

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

#define NOERROR 0
#define MEMERR  1
#define READERR 2
#define CODERR  3
#define WRITERR 4
#define BUFOVF  5
#define ENDFILE 7

#define INTBUFLNG 2048

static void help()
{
printf("\n\n");
printf("AGL - ASCII to standard metafile ");
printf("conversion utility (v. 3.52)\n\n");
printf("Usage: mf2ascii [ascii metafile] [standard metafile]\n\n");
printf("       where: ascii metafile    - Input ascii file name\n\n");
printf("              standard metafile - Output metafile name\n");
printf("If input and/or output file names are ");
printf("not provided, they are prompted.\n\n");
printf("Copyright 1989 by L. Fini. This program may be freely ");
printf("copied and used\n");
printf("provided this copyright notice will remain attached to it.\n");
}


static char *field(chstrg)
char *chstrg;                /* returns pointer to next data field          */
{
while((*chstrg!='\0')&&(*chstrg!=' ')) chstrg++;
while((*chstrg!='\0')&&(*chstrg==' ')) chstrg++;
if(chstrg=='\0') return NULL;
return (chstrg);
}


static enum METACODE find(key)		/* Returns index corresponding    */
					/* to key or (-1)                 */
char *key;
{
int first,last,middle,found=(-1);
static struct jptab { 				/* keyword table          */
	char kwd[4];
	enum METACODE code;
} kwtable[] = { 	{ {'C','D','E','F'},  MFCDEF },
			{ {'E','S','C',' '},  MFESC  }, 
			{ {'E','X','T','N'},  MFEXTN },
			{ {'G','I','N','T'},  MFGINT },
			{ {'G','P','L','L'},  MFGPLL },
			{ {'G','P','L','M'},  MFGPLM },
			{ {'G','T','X','T'},  MFGTXT },
			{ {'S','S','E','T'},  MFSSET },
			{ {'V','E','R','S'},  MFVERS },
			{ {'W','D','E','F'},  MFWDEF }
};

#define LAST  sizeof(kwtable)/sizeof(struct jptab) - 1


first=0;
last=LAST;

while ((last>=first)&&(found<0)) {
	int cmp;
	middle = (last+first)/2;
	cmp=strncmp(key,kwtable[middle].kwd,4);
	if(cmp < 0)
		last=middle-1;
	else if (cmp > 0)
		first=middle+1;
	else
		found=middle;
}
return(found>=0 ? kwtable[found].code : MFILLC);
}


main(argc,argv)
int argc;
char *argv[];
{
FILE *in=NULL, *out=NULL;
int aux=0;
int is,i,ic;
enum METACODE code;
char *header=MFHEAD;
int retstat;
long nlinein;
char *pt;
char nambuf[PHNAMLNG];
char buffr[INTBUFLNG];
float xxx[4];

xxx[0]++;				/* Ma guarda che mi tocca fare !! */
                                        /* Mannaggia all' MSC             */
for(i=1; i<argc; i++) {
	char *pt = argv[i];
	if(*pt == '?') {
		help();
		return 0;
	}
  
	if(aux==0) {
		in=fopen(argv[i],"r");		/* Open input metafile     */
		if(in==NULL) {
			fprintf(stderr,"\nError opening file %s as input\n",argv[i]);
			return 0;
		}
		aux=1;
		continue;
	}
   
	if(aux==1) {
		out=fopen(argv[i],B_CREATE);

		if ( out == NULL ) {
			fprintf(stderr,"\nError opening file %s as output\n",argv[i]);
			return 0;
		}
		aux=2;
		continue;
	}
}

if(in==NULL) {
	printf("\nInput file name (return to exit): ");
	scanf("%s",nambuf);
	if(*nambuf=='\0') return 0;
	in = fopen(nambuf,"r");			/* Open input ascii file    */
	if(in==NULL) {
		fprintf(stderr,"\nError opening file %s as input\n",nambuf);
		return 0;
	}
}

(void)fgets (buffr,INTBUFLNG,in);               /* Read metafile header    */
pt=buffr;
if(*pt=='#') 
	pt += 2;	/* Remain compatible with previous version         */

if(strncmp(pt,"AGL ASCII metafile",18) != 0) {
	fprintf(stderr,"\nInput file is not an AGL ASCII metafile\n");
	return 0;
}

if(out == NULL ) {
	printf("\nOutput file name (return to exit): ");
	scanf("%s",nambuf);
	if(*nambuf=='\0') return 0;
	out=fopen(nambuf,B_CREATE);
	if ( out == NULL ) {
		fprintf(stderr,"\nError opening file %s as output\n",nambuf);
		return 0;
	}
}


fwrite(header,sizeof(char),MFHDRLEN,out);

nlinein=0;
retstat=NOERROR;

while(retstat==NOERROR) {
	nlinein++;
	pt=fgets(buffr,INTBUFLNG,in);		/* get next metafile line   */
	if(pt==NULL) {
		if(feof(in))
			retstat=ENDFILE;
		else
			retstat=READERR;
	break;
	}

	pt=buffr;
	while(*pt) {				/* Convert into upper case  */
		*pt = TOUPPER(*pt);
		pt++;
	}

	pt=buffr+5;				/* Parameter address        */
  

	code=find(buffr);

	if(code==MFILLC) {
		retstat=CODERR;
		break;
	}

	switch(code) {
	int mark;
	int cntr,leng;
	int aux;
	int ictarget;
	char *auxbuf;
	char *auxpt;

	case MFGPLL:				/* AG_GPLL                   */
	case MFGPLM:				/* AG_GPLM Command           */
	case MFGINT:				/* AG_GINT Command           */
		if(code==MFGPLM) {
			ictarget=2;
			ic=sscanf (pt,"%d %d",&mark,&leng);
		} else {
			ictarget=1;
			ic=sscanf (pt,"%d",&leng);	/* get vector length */
		}
		if(ic!=ictarget) { 
			retstat=READERR; 
			break; 
		}
		is = fwrite((void *)&code,sizeof(enum METACODE),1,out);
		if(code==MFGPLM)
			is = fwrite((void *)&mark,sizeof(int),1,out);
		is = fwrite((void *)&leng,sizeof(int),1,out);

		while(leng--) {
			nlinein++;
			pt=fgets(buffr,INTBUFLNG,in);
			ic=sscanf (pt,"%e %e",xxx,xxx+1);
			if(ic!=2) { 
				retstat=READERR; 
				break; 
			}
			ic = fwrite((void *)xxx,sizeof(float),2,out);
			if(ic!=2) { retstat=WRITERR; break; }
		}
		break;

	case MFGTXT:
		ic=sscanf (pt,"%e %e %d %d",xxx, xxx+1, &cntr, &leng);
		if(ic!=4) { 
			retstat=READERR; 
			break; 
		}

		is = fwrite((void *)&code,sizeof(enum METACODE),1,out);
		is = fwrite((void *)xxx,sizeof(float),2,out);
		is = fwrite((void *)&cntr,sizeof(int),1,out);
		is = fwrite((void *)&leng,sizeof(int),1,out);

		if(leng>INTBUFLNG) { 
			retstat=BUFOVF; 
			break; 
		}

		nlinein++;
		pt=fgets(buffr,INTBUFLNG,in);	/* get next metafile line   */
		is = fwrite((void *)buffr,sizeof(char),leng,out);
		if(is!=leng) { 
			retstat=WRITERR; 
			break; 
		}
		break;

	case MFSSET:                           /* SET Command                 */
		ic=sscanf (pt,"%d",&leng);
		if(ic!=1) { 
			retstat=READERR; 
			break; 
		}
		is = fwrite((void *)&code,sizeof(enum METACODE),1,out);
		is = fwrite((void *)&leng,sizeof(int),1,out);

		if(leng>INTBUFLNG) { 
			retstat=BUFOVF; 
			break; 
		}

		nlinein++;
		pt=fgets(buffr,INTBUFLNG,in);	/* get next metafile line   */

		is = fwrite((void *)buffr,sizeof(char),leng,out);
		if(is!=leng) { 
			retstat=WRITERR; 
			break; 
		}
		break;        

	case MFESC:                                 /* Escape command         */
	case MFEXTN:
		ic=sscanf (pt,"%d",&leng);
		if(ic!=1) { 
			retstat=READERR; 
			break; 
		}

		is = fwrite((void *)&code,sizeof(enum METACODE),1,out);
		is = fwrite((void *)&leng,sizeof(int),1,out);

		auxbuf=(char *)malloc((size_t)leng);
		if(auxbuf==NULL) { 
			retstat=MEMERR; 
			break; 
		}
		auxpt=auxbuf;
		pt=NULL;

		aux=leng;
		while(aux--) {
			int an_int;
			if(pt==NULL) {
				nlinein++;
				pt=fgets(buffr,INTBUFLNG,in);
				if(pt==NULL) { 
					retstat=READERR; 
					break; 
				}
			}
			ic=sscanf(pt,"%x",&an_int);
			*auxpt++ = an_int;
			if(ic!=1) { 
				retstat=READERR; 
				break; 
			}
			pt=field(pt);		/* get next data field      */
		}
		if(retstat!=NOERROR) { 
			retstat=READERR; 
			break; 
		}
		is = fwrite((void *)auxbuf,sizeof(char),leng,out);
		if(is!=leng) { 
			retstat=WRITERR; 
			break; 
		}
		free(auxbuf);
		break;

	case MFVERS:                         /* ERASE Command                */
		is = fwrite((void *)&code,sizeof(enum METACODE),1,out);
		if(is!=1) { 
			retstat=WRITERR; 
			break; 
		}
		break; 

	case MFCDEF:
	case MFWDEF:
		ic=sscanf (pt,"%e %e %e %e",xxx,xxx+1,xxx+2,xxx+3);
		if(ic!=4) { 
			retstat=READERR; 
			break; 
		}

		is = fwrite((char *)&code,sizeof(enum METACODE),1,out);
		is = fwrite((char *)xxx,sizeof(float),4,out);
		if(is!=4) { 
			retstat=WRITERR; 
			break; 
		}
	}
}

switch(retstat) {
case ENDFILE:
	break;

default:
case NOERROR:
	fprintf(stderr,"\nInternal error!!!\n");
	break;

case WRITERR:
	fprintf(stderr,"\nError writing to output file\n");
	break;

case READERR:
	fprintf(stderr,"\nError reading from input file at line %ld\n",nlinein);
	break;

case CODERR:
	fprintf(stderr,"\nIllegal metafile code at line %ld\n",nlinein);
	break;

case BUFOVF:
	fprintf(stderr,"\nInternal buffer overflow at line %ld\n",nlinein);
	break;

}

fclose(in);
fclose(out);
return 0;
}
