/* input routines */

#include "nroff.h"

/*
 * standard reading routine
 */

getm()
{
	int	c;
	register struct	source	*mp;

	mp = curmacro;
	for(;;){
		c = *mp->m_curp++;
		if(c != 0)
			return(c);
		/*
		 * it's a file !!
		 */
		if(mp->m_fp != NULL){
			c = fread(mp->m_val, 1, LINESIZE, mp->m_fp);
			mp->m_val[c] = '\0';
			if(c){
				mp->m_curp = mp->m_val;
				continue;
			}
			/* 
			 * at end of current file
			 */
			if(mp->m_last != 0){
				/* a .so */
				curmacro = mp->m_last;
				myfree(mp->m_val);
				fclose(mp->m_fp);
				myfree( (char *)mp);
				mp = curmacro;
				nsources--;
				continue;
			}
			/* stdin */
			clearerr(mp->m_fp);
			mp->m_curp = mp->m_val;
			*mp->m_curp = '\0';
			return(EOF);
		}
		/*
		 * end of current argument ?
		 */
		if(mp->m_scurp != 0){
			mp->m_curp = mp->m_scurp;
			mp->m_scurp = 0;
			continue;
		}
		if(mp->m_name[0] == '\0'){
			/* thing has no name - delete */
			curmacro = mp->m_last;
			myfree(mp->m_val);
			myfree( (char *)mp);
			mp = curmacro;
			continue;
		}
		/* end of macro */
		mp = curmacro->m_last;
		curmacro->m_last = 0;
		curmacro = mp;
		if(mp == 0){
			fprintf(stderr, "Macro stack corrupt\n");
			exit(5);
		}
	}
}

ngets(inb, cmode)
char	*inb;
{
	int	c;
	int	curpos = 0;
	struct	source	*mp;

	c = getm();
	if(CMD(c))
		cmode = TRUE;
	for(;c != EOF; c = getm()){
		if(c != echar){
			/* not an escape char it's boring */
			if(c == '\t'){
				do {
					*inb++ = ' ';
					curpos++;
				}while((curpos & 7) != 0);
				continue;
			}
			if(c == '\n'){
				*inb = '\0';
				return(1);
			}
			*inb++ = c;
			curpos++;
			continue;
		}
		switch(c = getm()){
		case '\n':	/* concealed newlines */
			continue;
		case '"':	/* comments for macros etc. */
			do {
				c = getm();
			}while(c != '\n' && c != EOF);
			if(c == EOF)
				return(0);
			if(curpos == 0)
				continue;
			*inb = '\0';
			return(1);
		case '*':
			/* time for a register read */
			regread();
			continue;
		case 'n':
			/* number read */
			numread();
			continue;
		case '$':
			mp = curmacro;
			if(mp->m_scurp)
				continue;
			if(*mp->m_curp == '\0')
				continue;
			c = *mp->m_curp++;
			c -= '1';
			if(c < 0)
				continue;
				/* about to go into arguments */
				/* must go and find them !! */
			for(;mp ; mp = mp->m_last){
				if(mp->m_type != AMACRO)
					continue;
				if(mp->m_name[0] == '\0')
					continue;
				if(mp->m_scurp== 0 && c < mp->m_nargs){
					curmacro->m_scurp = curmacro->m_curp;
					curmacro->m_curp = mp->m_args[c];
				}
				break;
			}
			continue;
		default:
			if(cmode && (c == echar || c == cmdchar1)){
				*inb++ = c;
				curpos++;
				continue;
			}
			*inb++ = echar;
			*inb++ = c;
			curpos += 2;
			continue;
		}
	}
	return(0);
}
