/***  io.c  ***/

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

#include "lalgol.h"
#include "io.h"
#include "data.h"

/*----------------------------------------------------------------------*/
/* input/output files */
FILE *infile,*print_file,*prog_file;

void open_files(argc,argv) int argc; char *argv[];
{	if(argc<3){
	    fprintf(stderr,"%s\n","args: %work1 %work2 [input_file]");
	    exit(1);
	}
	if((print_file=fopen(argv[1],"wb"))==NULL){
	    fprintf(stderr,"couldn't create file %s, aborted\n",argv[1]);
	    exit(1);
	}
	if((prog_file=fopen(argv[2],"wb"))==NULL){
	    fprintf(stderr,"couldn't create file %s, aborted\n",argv[2]);
	    exit(1);
	}
	if((infile =argc<4?stdin:fopen(argv[3],"rt"))==NULL){
	    fprintf(stderr,"couldn't find file %s, aborted\n",argv[3]);
	    exit(1);
	}
}

void close_files()
{	if(!was_error)fprintf(print_file,"\n*****");
	putc('\n',print_file); putc(0,print_file);
	putc(symbol_counter>>8,print_file); putc(symbol_counter,print_file);
	putc(data_counter>>8,print_file); putc(data_counter,print_file);
	putc(was_error,print_file); putc(0,print_file);
	fclose(print_file);
	fwrite(&DATA[1],sizeof(int),data_counter,prog_file);
	putc(0,prog_file); fclose(prog_file);
}

/*----------------------------------------------------------------------
 * int ch:		the next character
 * int symbol_counter:	number of symbols written out
 * int last_char; bool next_line, error_here;
 *			are used to make nice listing
 * bool nomad_or_colon(char), is_letter(char), is_letgit(char),
	is_string_char(char), is_digit(char), is_base_digit(base,char);
 * int sort_of(char);
 * int next_char() -> ch, next_visible_char() -> ch;
 * bool was_error;
 *----------------------------------------------------------------------*/

int SORT[] = {	_SCF,					    /* EOF        */
		_SCF     ,_SCF|_TWG,_SCF|_TWG,_SCF|_TWG,    /*  0  1  2  3*/
		_SCF|_TWG,_SCF|_TWG,_SCF|_TWG,_SCF|_TWG,    /*  4  5  6  7*/
		_SCF|_TWG,_TLY     ,_SCF|_TLY,_SCF|_TLY,    /* \b \t \n 13*/
		_SCF|_TLY,_SCF|_TLY,_SCF|_TWG,_SCF|_TWG,    /* \r \f 16 17*/
		_SCF|_TWG,_SCF|_TWG,_SCF|_TWG,_SCF|_TWG,    /* 20 21 22 23*/
		_SCF|_TWG,_SCF|_TWG,_SCF|_TWG,_SCF|_TWG,    /* 24 25 26 27*/
		_SCF|_TWG,_SCF|_TWG,_SCF|_TWG,_SCF|_TWG,    /* 30 31 32 33*/
		_SCF|_TWG,_SCF|_TWG,_SCF|_TWG,_SCF|_TWG,    /* 34 35 36 37*/
		_TLY     ,_TNM     ,_SCF     ,0        ,    /* sp !  "  # */
		_TWG	 ,_TNM	   ,_TNM     ,0	       ,    /* $  %  &  ' */
		0	 ,0	   ,_NCF|_TNM,_TNM     ,    /* (  )  *  + */
		0	 ,_TNM	   ,_TDP     ,_NCF|_TNM,    /* ,  -  .  / */
		_D2F|_DGF|_TDP,_D2F|_DGF|_TDP,_D4F|_DGF|_TDP,_D4F|_DGF|_TDP,
							    /* 0  1  2  3 */
		_D8F|_DGF|_TDP,_D8F|_DGF|_TDP,_D8F|_DGF|_TDP,_D8F|_DGF|_TDP,
							    /* 4  5  6  7 */
		_DXF|_DGF|_TDP,_DXF|_DGF|_TDP,_NCF|_TNM,0,  /* 8  9  :  ; */
		_NCF|_TNM,_NCF|_TNM,_NCF|_TNM,_TNM,	    /* <  =  >  ? */
		0	 ,_DXF|_TLT,_DXF|_TLT,_DXF|_TLT,   /* @  A  B  C */
		_DXF|_TLT,_DXF|_TLT,_DXF|_TLT,_TLT     ,   /* D  E  F  G */
		_TLT	 ,_TLT     ,_TLT     ,_TLT     ,   /* H  I  J  K */
		_TLT	 ,_TLT	   ,_TLT     ,_TLT     ,   /* L  M  N  O */
		_TLT	 ,_TLT	   ,_TLT     ,_TLT     ,   /* P  Q  R  S */
		_TLT	 ,_TLT	   ,_TLT     ,_TLT     ,   /* T  U  V  W */
		_TLT	 ,_TLT	   ,_TLT     ,0	       ,   /* X  Y  Z  [ */
		_TWG	 ,0	   ,_TNM     ,_TWG     ,   /* \  ]  ^  _ */
		_TWG	 ,_DXF|_TLT,_DXF|_TLT,_DXF|_TLT,   /* `  a  b  c */
		_DXF|_TLT,_DXF|_TLT,_DXF|_TLT,_TLT     ,   /* d  e  f  g */
		_TLT	 ,_TLT	   ,_TLT     ,_TLT     ,   /* h  i  j  k */
		_TLT	 ,_TLT	   ,_TLT     ,_TLT     ,   /* l  m  n  o */
		_TLT	 ,_TLT	   ,_TLT     ,_TLT     ,   /* p  q  r  s */
		_TLT	 ,_TLT	   ,_TLT     ,_TLT     ,   /* t  u  v  w */
		_TLT	 ,_TLT	   ,_TLT     ,_TWG     ,   /* x  y  z  { */
		0	 ,_TWG	   ,_TNM     ,_SCF|_TWG	   /* |  }  ~  0177 */
	};

static int  last_char='\n';
static bool next_line=TRUE, error_here=FALSE;

/*------------------------------------------------------------------------*/
static void print_char(int);

static void print_char(c) int c;
{	if(last_char=='\n') next_line=TRUE;
	else{
	    if(next_line){
		fprintf(print_file,"\n%4d\t",symbol_counter);
		next_line=FALSE;
	    }
	    fprintf(print_file,"%c",last_char); error_here=FALSE;
	}
	last_char= c>0?c:'\n';
}

int next_char()
{	while((ch=getc(infile))>0177 || !ch); print_char(ch);
	return(ch);
}

int next_visible_char()
{	while(sort_of(next_char())==layout_t); return(ch);
}

void skip_short_comment()
{	while(next_char()!='#' && ch != EOF); next_visible_char();
}

void skip_comment(type) int type;
{back:	if(ch==EOF) return;
	if(ch!='\''){next_char(); goto back;}
	if(next_char()!='c'||next_char()!='o') goto back;
	if(type==COMMENT &&(next_char()!='m'||next_char()!='m'||
		next_char()!='e'||next_char()!='n'||next_char()!='t'))
			goto back;
	if(next_char()!='\'') goto back;
	next_visible_char();
}

/*----------------------------------------------------------------------*/
/*  error handling  */

void error(s) char *s;
{	if(error_here) return;
	error_here=was_error=next_line=TRUE;
	fprintf(print_file,"\n*** ERROR ***   %s",s);
}

void fatal_error(s) char *s;
{	fprintf(print_file,"\n*** ERROR ***   %s",s);
	was_error=TRUE; close_files(); exit(7);
}

/*----------------------------------------------------------------------*/

void put_symbol(s) int s;
{	if((++symbol_counter)==3 && s !=OPEN)
	    fatal_error("the program must start with an open symbol");
	putc(s>>8,prog_file); putc(s,prog_file);
}

