#include "a.h"

/*
 * 19. Input/output file switching.
 */

/* .so - push new source file */
void
r_so(int argc, Rune **argv)
{
	USED(argc);
	pushinputfile(erunesmprint("%s", unsharp(esmprint("%S", argv[1]))));
}

/* .nx - end this file, switch to arg */
void
r_nx(int argc, Rune **argv)
{
	int n;
	
	if(argc == 1){
		while(popinput())
			;
	}else{
		if(argc > 2)
			warn("too many arguments for .nx");
		while((n=popinput()) && n != 2)
			;
		pushinputfile(argv[1]);
	}
}

/* .sy - system: run string */
void
r_sy(Rune *name)
{
	USED(name);
	warn(".sy not implemented");
}

/* .pi - pipe output to string */
void
r_pi(Rune *name)
{
	USED(name);
	warn(".pi not implemented");
}

/* .cf - copy contents of filename to output */
void
r_cf(int argc, Rune **argv)
{
	int c;
	char *p;
	Biobuf *b;

	USED(argc);
	p = esmprint("%S", argv[1]);
	if((b = Bopen(p, OREAD)) == nil){
		fprint(2, "%L: open %s: %r\n", p);
		free(p);
		return;
	}
	free(p);

	while((c = Bgetrune(b)) >= 0)
		outrune(c);
	Bterm(b);
}

void
r_inputpipe(Rune *name)
{
	Rune *cmd, *stop, *line;
	int n, pid, p[2], len;
	Waitmsg *w;
	
	USED(name);
	if(pipe(p) < 0){
		warn("pipe: %r");
		return;
	}
	stop = copyarg();
	cmd = readline(CopyMode);
	pid = fork();
	switch(pid){
	case 0:
		if(p[0] != 0){
			dup(p[0], 0);
			close(p[0]);
		}
		close(p[1]);
		execl(unsharp("#9/bin/rc"), "rc", "-c", esmprint("%S", cmd), nil);
		warn("%Cdp %S: %r", dot, cmd);
		_exits(nil);
	case -1:
		warn("fork: %r");
	default:
		close(p[0]);
		len = runestrlen(stop);
		fprint(p[1], ".ps %d\n", getnr(L(".s")));
		fprint(p[1], ".vs %du\n", getnr(L(".v")));
		fprint(p[1], ".ft %d\n", getnr(L(".f")));
		fprint(p[1], ".ll 8i\n");
		fprint(p[1], ".pl 30i\n");
		while((line = readline(~0)) != nil){
			if(runestrncmp(line, stop, len) == 0 
			&& (line[len]==' ' || line[len]==0 || line[len]=='\t'
				|| (line[len]=='\\' && line[len+1]=='}')))
				break;
			n = runestrlen(line);
			line[n] = '\n';
			fprint(p[1], "%.*S", n+1, line);
			free(line);
		}
		free(stop);
		close(p[1]);
		w = wait();
		if(w == nil){
			warn("wait: %r");
			return;
		}
		if(w->msg[0])
			sysfatal("%C%S %S: %s", dot, name, cmd, w->msg);
		free(cmd);
		free(w);
	}
}	

void
t19init(void)
{
	addreq(L("so"), r_so, 1);
	addreq(L("nx"), r_nx, -1);
	addraw(L("sy"), r_sy);
	addraw(L("inputpipe"), r_inputpipe);
	addraw(L("pi"), r_pi);
	addreq(L("cf"), r_cf, 1);
	
	nr(L("$$"), getpid());
}

