xref: /csrg-svn/old/awk/run.c (revision 14474)
1 #ifndef lint
2 static char sccsid[] = "@(#)run.c	4.4 08/11/83";
3 #endif
4 
5 #include "awk.def"
6 #include	"math.h"
7 #include "awk.h"
8 #include "stdio.h"
9 #define RECSIZE BUFSIZ
10 
11 #define FILENUM	10
12 struct
13 {
14 	FILE *fp;
15 	char *fname;
16 } files[FILENUM];
17 FILE *popen();
18 
19 extern obj execute(), nodetoobj(), fieldel(), dopa2(), gettemp();
20 #define PA2NUM	29
21 int pairstack[PA2NUM], paircnt;
22 node *winner = (node *)NULL;
23 #define MAXTMP 20
24 cell tmps[MAXTMP];
25 static cell nullval ={EMPTY,EMPTY,0.0,NUM,0};
26 obj	true	={ OBOOL, BTRUE, 0 };
27 obj	false	={ OBOOL, BFALSE, 0 };
28 
29 run()
30 {
31 	execute(winner);
32 }
33 
34 obj execute(u) node *u;
35 {
36 	register obj (*proc)();
37 	obj x;
38 	node *a;
39 	extern char *printname[];
40 
41 	if (u==(node *)NULL)
42 		return(true);
43 	for (a = u; ; a = a->nnext) {
44 		if (cantexec(a))
45 			return(nodetoobj(a));
46 		if (a->ntype==NPA2)
47 			proc=dopa2;
48 		else {
49 			if (notlegal(a->nobj))
50 				error(FATAL, "illegal statement %o", a);
51 			proc = proctab[a->nobj-FIRSTTOKEN];
52 		}
53 		x = (*proc)(a->narg,a->nobj);
54 		if (isfld(x)) fldbld();
55 		if (isexpr(a))
56 			return(x);
57 		/* a statement, goto next statement */
58 		if (isjump(x))
59 			return(x);
60 		if (a->nnext == (node *)NULL)
61 			return(x);
62 		tempfree(x);
63 	}
64 }
65 
66 obj program(a, n) node **a;
67 {
68 	obj x;
69 
70 	if (a[0] != NULL) {
71 		x = execute(a[0]);
72 		if (isexit(x))
73 			return(true);
74 		if (isjump(x))
75 			error(FATAL, "unexpected break, continue or next");
76 		tempfree(x);
77 	}
78 	while (getrec()) {
79 		x = execute(a[1]);
80 		if (isexit(x)) break;
81 		tempfree(x);
82 	}
83 	tempfree(x);
84 	if (a[2] != NULL) {
85 		x = execute(a[2]);
86 		if (isbreak(x) || isnext(x) || iscont(x))
87 			error(FATAL, "unexpected break, continue or next");
88 		tempfree(x);
89 	}
90 	return(true);
91 }
92 
93 obj getline()
94 {
95 	obj x;
96 
97 	x = gettemp();
98 	setfval(x.optr, (awkfloat) getrec());
99 	return(x);
100 }
101 
102 obj array(a,n) node **a;
103 {
104 	obj x, y;
105 	extern obj arrayel();
106 
107 	x = execute(a[1]);
108 	y = arrayel(a[0], x);
109 	tempfree(x);
110 	return(y);
111 }
112 
113 obj arrayel(a,b) node *a; obj b;
114 {
115 	char *s;
116 	cell *x;
117 	int i;
118 	obj y;
119 
120 	s = getsval(b.optr);
121 	x = (cell *) a;
122 	if (!(x->tval&ARR)) {
123 		strfree(x->sval);
124 		x->tval &= ~STR;
125 		x->tval |= ARR;
126 		x->sval = (char *) makesymtab();
127 	}
128 	y.optr = setsymtab(s, tostring(""), 0.0, STR|NUM, x->sval);
129 	y.otype = OCELL;
130 	y.osub = CVAR;
131 	return(y);
132 }
133 
134 obj matchop(a,n) node **a;
135 {
136 	obj x;
137 	char *s;
138 	int i;
139 
140 	x = execute(a[0]);
141 	if (isstr(x)) s = x.optr->sval;
142 	else	s = getsval(x.optr);
143 	tempfree(x);
144 	i = match(a[1], s);
145 	if (n==MATCH && i==1 || n==NOTMATCH && i==0)
146 		return(true);
147 	else
148 		return(false);
149 }
150 
151 obj boolop(a,n) node **a;
152 {
153 	obj x, y;
154 	int i;
155 
156 	x = execute(a[0]);
157 	i = istrue(x);
158 	tempfree(x);
159 	switch (n) {
160 	default:
161 		error(FATAL, "unknown boolean operator %d", n);
162 	case BOR:
163 		if (i) return(true);
164 		y = execute(a[1]);
165 		i = istrue(y);
166 		tempfree(y);
167 		if (i) return(true);
168 		else return(false);
169 	case AND:
170 		if ( !i ) return(false);
171 		y = execute(a[1]);
172 		i = istrue(y);
173 		tempfree(y);
174 		if (i) return(true);
175 		else return(false);
176 	case NOT:
177 		if (i) return(false);
178 		else return(true);
179 	}
180 }
181 
182 obj relop(a,n) node **a;
183 {
184 	int i;
185 	obj x, y;
186 	awkfloat j;
187 
188 	x = execute(a[0]);
189 	y = execute(a[1]);
190 	if (x.optr->tval&NUM && y.optr->tval&NUM) {
191 		j = x.optr->fval - y.optr->fval;
192 		i = j<0? -1: (j>0? 1: 0);
193 	} else {
194 		i = strcmp(getsval(x.optr), getsval(y.optr));
195 	}
196 	tempfree(x);
197 	tempfree(y);
198 	switch (n) {
199 	default:
200 		error(FATAL, "unknown relational operator %d", n);
201 	case LT:	if (i<0) return(true);
202 			else return(false);
203 	case LE:	if (i<=0) return(true);
204 			else return(false);
205 	case NE:	if (i!=0) return(true);
206 			else return(false);
207 	case EQ:	if (i==0) return(true);
208 			else return(false);
209 	case GE:	if (i>=0) return(true);
210 			else return(false);
211 	case GT:	if (i>0) return(true);
212 			else return(false);
213 	}
214 }
215 
216 tempfree(a) obj a;
217 {
218 	if (!istemp(a)) return;
219 	strfree(a.optr->sval);
220 	a.optr->tval = 0;
221 }
222 
223 obj gettemp()
224 {
225 	int i;
226 	obj x;
227 
228 	for (i=0; i<MAXTMP; i++)
229 		if (tmps[i].tval==0)
230 			break;
231 	if (i==MAXTMP)
232 		error(FATAL, "out of temporaries in gettemp");
233 	x.optr = &tmps[i];
234 	tmps[i] = nullval;
235 	x.otype = OCELL;
236 	x.osub = CTEMP;
237 	return(x);
238 }
239 
240 obj indirect(a,n) node **a;
241 {
242 	obj x;
243 	int m;
244 	cell *fieldadr();
245 
246 	x = execute(a[0]);
247 	m = getfval(x.optr);
248 	tempfree(x);
249 	x.optr = fieldadr(m);
250 	x.otype = OCELL;
251 	x.osub = CFLD;
252 	return(x);
253 }
254 
255 obj substr(a, nnn) node **a;
256 {
257 	char *s, temp;
258 	obj x;
259 	int k, m, n;
260 
261 	x = execute(a[0]);
262 	s = getsval(x.optr);
263 	k = strlen(s) + 1;
264 	tempfree(x);
265 	x = execute(a[1]);
266 	m = getfval(x.optr);
267 	if (m <= 0)
268 		m = 1;
269 	else if (m > k)
270 		m = k;
271 	tempfree(x);
272 	if (a[2] != nullstat) {
273 		x = execute(a[2]);
274 		n = getfval(x.optr);
275 		tempfree(x);
276 	}
277 	else
278 		n = k - 1;
279 	if (n < 0)
280 		n = 0;
281 	else if (n > k - m)
282 		n = k - m;
283 	dprintf("substr: m=%d, n=%d, s=%s\n", m, n, s);
284 	x = gettemp();
285 	temp = s[n+m-1];	/* with thanks to John Linderman */
286 	s[n+m-1] = '\0';
287 	setsval(x.optr, s + m - 1);
288 	s[n+m-1] = temp;
289 	return(x);
290 }
291 
292 obj sindex(a, nnn) node **a;
293 {
294 	obj x;
295 	char *s1, *s2, *p1, *p2, *q;
296 
297 	x = execute(a[0]);
298 	s1 = getsval(x.optr);
299 	tempfree(x);
300 	x = execute(a[1]);
301 	s2 = getsval(x.optr);
302 	tempfree(x);
303 
304 	x = gettemp();
305 	for (p1 = s1; *p1 != '\0'; p1++) {
306 		for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
307 			;
308 		if (*p2 == '\0') {
309 			setfval(x.optr, (awkfloat) (p1 - s1 + 1));	/* origin 1 */
310 			return(x);
311 		}
312 	}
313 	setfval(x.optr, 0.0);
314 	return(x);
315 }
316 
317 char *format(s,a) char *s; node *a;
318 {
319 	char *buf, *p, fmt[200], *t, *os;
320 	obj x;
321 	int flag = 0;
322 	awkfloat xf;
323 
324 	os = s;
325 	p = buf = (char *)malloc(RECSIZE);
326 	while (*s) {
327 		if (*s != '%') {
328 			*p++ = *s++;
329 			continue;
330 		}
331 		if (*(s+1) == '%') {
332 			*p++ = '%';
333 			s += 2;
334 			continue;
335 		}
336 		for (t=fmt; (*t++ = *s) != '\0'; s++)
337 			if (*s >= 'a' && *s <= 'z' && *s != 'l')
338 				break;
339 		*t = '\0';
340 		if (t >= fmt + sizeof(fmt))
341 			error(FATAL, "format item %.20s... too long", os);
342 		switch (*s) {
343 		case 'f': case 'e': case 'g':
344 			flag = 1;
345 			break;
346 		case 'd':
347 			flag = 2;
348 			if(*(s-1) == 'l') break;
349 			*(t-1) = 'l';
350 			*t = 'd';
351 			*++t = '\0';
352 			break;
353 		case 'o': case 'x':
354 			flag = *(s-1)=='l' ? 2 : 3;
355 			break;
356 		case 'c':
357 			flag = 3;
358 			break;
359 		case 's':
360 			flag = 4;
361 			break;
362 		default:
363 			flag = 0;
364 			break;
365 		}
366 		if (flag == 0) {
367 			sprintf(p, "%s", fmt);
368 			p += strlen(p);
369 			continue;
370 		}
371 		if (a == NULL)
372 			error(FATAL, "not enough arguments in printf(%s)", os);
373 		x = execute(a);
374 		a = a->nnext;
375 		if (flag != 4)	/* watch out for converting to numbers! */
376 			xf = getfval(x.optr);
377 		if (flag==1) sprintf(p, fmt, xf);
378 		else if (flag==2) sprintf(p, fmt, (long)xf);
379 		else if (flag==3) sprintf(p, fmt, (int)xf);
380 		else if (flag==4) sprintf(p, fmt, x.optr->sval==NULL ? "" : getsval(x.optr));
381 		tempfree(x);
382 		p += strlen(p);
383 		s++;
384 	}
385 	*p = '\0';
386 	return(buf);
387 }
388 
389 obj asprintf(a,n) node **a;
390 {
391 	obj x;
392 	node *y;
393 	char *s;
394 
395 	y = a[0]->nnext;
396 	x = execute(a[0]);
397 	s = format(getsval(x.optr), y);
398 	tempfree(x);
399 	x = gettemp();
400 	x.optr->sval = s;
401 	x.optr->tval = STR;
402 	return(x);
403 }
404 
405 obj arith(a,n) node **a;
406 {
407 	awkfloat i,j;
408 	obj x,y,z;
409 
410 	x = execute(a[0]);
411 	i = getfval(x.optr);
412 	tempfree(x);
413 	if (n != UMINUS) {
414 		y = execute(a[1]);
415 		j = getfval(y.optr);
416 		tempfree(y);
417 	}
418 	z = gettemp();
419 	switch (n) {
420 	default:
421 		error(FATAL, "illegal arithmetic operator %d", n);
422 	case ADD:
423 		i += j;
424 		break;
425 	case MINUS:
426 		i -= j;
427 		break;
428 	case MULT:
429 		i *= j;
430 		break;
431 	case DIVIDE:
432 		if (j == 0)
433 			error(FATAL, "division by zero");
434 		i /= j;
435 		break;
436 	case MOD:
437 		if (j == 0)
438 			error(FATAL, "division by zero");
439 		i = i - j*(long)(i/j);
440 		break;
441 	case UMINUS:
442 		i = -i;
443 		break;
444 	}
445 	setfval(z.optr, i);
446 	return(z);
447 }
448 
449 obj incrdecr(a, n) node **a;
450 {
451 	obj x, z;
452 	int k;
453 	awkfloat xf;
454 
455 	x = execute(a[0]);
456 	xf = getfval(x.optr);
457 	k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
458 	if (n == PREINCR || n == PREDECR) {
459 		setfval(x.optr, xf + k);
460 		return(x);
461 	}
462 	z = gettemp();
463 	setfval(z.optr, xf);
464 	setfval(x.optr, xf + k);
465 	tempfree(x);
466 	return(z);
467 }
468 
469 
470 obj assign(a,n) node **a;
471 {
472 	obj x, y;
473 	awkfloat xf, yf;
474 
475 	x = execute(a[0]);
476 	y = execute(a[1]);
477 	if (n == ASSIGN) {	/* ordinary assignment */
478 		if ((y.optr->tval & (STR|NUM)) == (STR|NUM)) {
479 			setsval(x.optr, y.optr->sval);
480 			x.optr->fval = y.optr->fval;
481 			x.optr->tval |= NUM;
482 		}
483 		else if (y.optr->tval & STR)
484 			setsval(x.optr, y.optr->sval);
485 		else if (y.optr->tval & NUM)
486 			setfval(x.optr, y.optr->fval);
487 		tempfree(y);
488 		return(x);
489 	}
490 	xf = getfval(x.optr);
491 	yf = getfval(y.optr);
492 	switch (n) {
493 	case ADDEQ:
494 		xf += yf;
495 		break;
496 	case SUBEQ:
497 		xf -= yf;
498 		break;
499 	case MULTEQ:
500 		xf *= yf;
501 		break;
502 	case DIVEQ:
503 		if (yf == 0)
504 			error(FATAL, "division by zero");
505 		xf /= yf;
506 		break;
507 	case MODEQ:
508 		if (yf == 0)
509 			error(FATAL, "division by zero");
510 		xf = xf - yf*(long)(xf/yf);
511 		break;
512 	default:
513 		error(FATAL, "illegal assignment operator %d", n);
514 		break;
515 	}
516 	tempfree(y);
517 	setfval(x.optr, xf);
518 	return(x);
519 }
520 
521 obj cat(a,q) node **a;
522 {
523 	obj x,y,z;
524 	int n1, n2;
525 	char *s;
526 
527 	x = execute(a[0]);
528 	y = execute(a[1]);
529 	getsval(x.optr);
530 	getsval(y.optr);
531 	n1 = strlen(x.optr->sval);
532 	n2 = strlen(y.optr->sval);
533 	s = (char *) malloc(n1 + n2 + 1);
534 	strcpy(s, x.optr->sval);
535 	strcpy(s+n1, y.optr->sval);
536 	tempfree(y);
537 	z = gettemp();
538 	z.optr->sval = s;
539 	z.optr->tval = STR;
540 	tempfree(x);
541 	return(z);
542 }
543 
544 obj pastat(a,n) node **a;
545 {
546 	obj x;
547 
548 	if (a[0]==nullstat)
549 		x = true;
550 	else
551 		x = execute(a[0]);
552 	if (istrue(x)) {
553 		tempfree(x);
554 		x = execute(a[1]);
555 	}
556 	return(x);
557 }
558 
559 obj dopa2(a,n) node **a;
560 {
561 	obj x;
562 
563 	if (pairstack[n]==0) {
564 		x = execute(a[0]);
565 		if (istrue(x))
566 			pairstack[n] = 1;
567 		tempfree(x);
568 	}
569 	if (pairstack[n] == 1) {
570 		x = execute(a[1]);
571 		if (istrue(x))
572 			pairstack[n] = 0;
573 		tempfree(x);
574 		x = execute(a[2]);
575 		return(x);
576 	}
577 	return(false);
578 }
579 
580 obj aprintf(a,n) node **a;
581 {
582 	obj x;
583 
584 	x = asprintf(a,n);
585 	if (a[1]==NULL) {
586 		printf("%s", x.optr->sval);
587 		tempfree(x);
588 		return(true);
589 	}
590 	redirprint(x.optr->sval, (int)a[1], a[2]);
591 	return(x);
592 }
593 
594 obj split(a,nnn) node **a;
595 {
596 	obj x;
597 	cell *ap;
598 	register char *s, *p;
599 	char *t, temp, num[5];
600 	register int sep;
601 	int n, flag;
602 
603 	x = execute(a[0]);
604 	s = getsval(x.optr);
605 	tempfree(x);
606 	if (a[2] == nullstat)
607 		sep = **FS;
608 	else {
609 		x = execute(a[2]);
610 		sep = getsval(x.optr)[0];
611 		tempfree(x);
612 	}
613 	ap = (cell *) a[1];
614 	freesymtab(ap);
615 	dprintf("split: s=|%s|, a=%s, sep=|%c|\n", s, ap->nval, sep);
616 	ap->tval &= ~STR;
617 	ap->tval |= ARR;
618 	ap->sval = (char *) makesymtab();
619 
620 	n = 0;
621 	if (sep == ' ')
622 		for (n = 0; ; ) {
623 			while (*s == ' ' || *s == '\t' || *s == '\n')
624 				s++;
625 			if (*s == 0)
626 				break;
627 			n++;
628 			t = s;
629 			do
630 				s++;
631 			while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
632 			temp = *s;
633 			*s = '\0';
634 			sprintf(num, "%d", n);
635 			if (isnumber(t))
636 				setsymtab(num, tostring(t), atof(t), STR|NUM, ap->sval);
637 			else
638 				setsymtab(num, tostring(t), 0.0, STR, ap->sval);
639 			*s = temp;
640 			if (*s != 0)
641 				s++;
642 		}
643 	else if (*s != 0)
644 		for (;;) {
645 			n++;
646 			t = s;
647 			while (*s != sep && *s != '\n' && *s != '\0')
648 				s++;
649 			temp = *s;
650 			*s = '\0';
651 			sprintf(num, "%d", n);
652 			if (isnumber(t))
653 				setsymtab(num, tostring(t), atof(t), STR|NUM, ap->sval);
654 			else
655 				setsymtab(num, tostring(t), 0.0, STR, ap->sval);
656 			*s = temp;
657 			if (*s++ == 0)
658 				break;
659 		}
660 	x = gettemp();
661 	x.optr->tval = NUM;
662 	x.optr->fval = n;
663 	return(x);
664 }
665 
666 obj ifstat(a,n) node **a;
667 {
668 	obj x;
669 
670 	x = execute(a[0]);
671 	if (istrue(x)) {
672 		tempfree(x);
673 		x = execute(a[1]);
674 	}
675 	else if (a[2] != nullstat) {
676 		tempfree(x);
677 		x = execute(a[2]);
678 	}
679 	return(x);
680 }
681 
682 obj whilestat(a,n) node **a;
683 {
684 	obj x;
685 
686 	for (;;) {
687 		x = execute(a[0]);
688 		if (!istrue(x)) return(x);
689 		tempfree(x);
690 		x = execute(a[1]);
691 		if (isbreak(x)) {
692 			x = true;
693 			return(x);
694 		}
695 		if (isnext(x) || isexit(x))
696 			return(x);
697 		tempfree(x);
698 	}
699 }
700 
701 obj forstat(a,n) node **a;
702 {
703 	obj x;
704 
705 	tempfree(execute(a[0]));
706 	for (;;) {
707 		if (a[1]!=nullstat) {
708 			x = execute(a[1]);
709 			if (!istrue(x)) return(x);
710 			else tempfree(x);
711 		}
712 		x = execute(a[3]);
713 		if (isbreak(x)) {	/* turn off break */
714 			x = true;
715 			return(x);
716 		}
717 		if (isnext(x) || isexit(x))
718 			return(x);
719 		tempfree(x);
720 		tempfree(execute(a[2]));
721 	}
722 }
723 
724 obj instat(a, n) node **a;
725 {
726 	cell *vp, *arrayp, *cp, **tp;
727 	obj x;
728 	int i;
729 
730 	vp = (cell *) a[0];
731 	arrayp = (cell *) a[1];
732 	if (!(arrayp->tval & ARR))
733 		error(FATAL, "%s is not an array", arrayp->nval);
734 	tp = (cell **) arrayp->sval;
735 	for (i = 0; i < MAXSYM; i++) {	/* this routine knows too much */
736 		for (cp = tp[i]; cp != NULL; cp = cp->nextval) {
737 			setsval(vp, cp->nval);
738 			x = execute(a[2]);
739 			if (isbreak(x)) {
740 				x = true;
741 				return(x);
742 			}
743 			if (isnext(x) || isexit(x))
744 				return(x);
745 			tempfree(x);
746 		}
747 	}
748 	return (true);
749 }
750 
751 obj jump(a,n) node **a;
752 {
753 	obj x, y;
754 
755 	x.otype = OJUMP;
756 	switch (n) {
757 	default:
758 		error(FATAL, "illegal jump type %d", n);
759 		break;
760 	case EXIT:
761 		if (a[0] != 0) {
762 			y = execute(a[0]);
763 			errorflag = getfval(y.optr);
764 		}
765 		x.osub = JEXIT;
766 		break;
767 	case NEXT:
768 		x.osub = JNEXT;
769 		break;
770 	case BREAK:
771 		x.osub = JBREAK;
772 		break;
773 	case CONTINUE:
774 		x.osub = JCONT;
775 		break;
776 	}
777 	return(x);
778 }
779 
780 obj fncn(a,n) node **a;
781 {
782 	obj x;
783 	awkfloat u;
784 	int t;
785 
786 	t = (int) a[0];
787 	x = execute(a[1]);
788 	if (t == FLENGTH)
789 		u = (awkfloat) strlen(getsval(x.optr));
790 	else if (t == FLOG)
791 		u = log(getfval(x.optr));
792 	else if (t == FINT)
793 		u = (awkfloat) (long) getfval(x.optr);
794 	else if (t == FEXP)
795 		u = exp(getfval(x.optr));
796 	else if (t == FSQRT)
797 		u = sqrt(getfval(x.optr));
798 	else
799 		error(FATAL, "illegal function type %d", t);
800 	tempfree(x);
801 	x = gettemp();
802 	setfval(x.optr, u);
803 	return(x);
804 }
805 
806 obj print(a,n) node **a;
807 {
808 	register node *x;
809 	obj y;
810 	char s[RECSIZE];
811 
812 	s[0] = '\0';
813 	for (x=a[0]; x!=NULL; x=x->nnext) {
814 		y = execute(x);
815 		strcat(s, getsval(y.optr));
816 		tempfree(y);
817 		if (x->nnext==NULL)
818 			strcat(s, *ORS);
819 		else
820 			strcat(s, *OFS);
821 	}
822 	if (strlen(s) >= RECSIZE)
823 		error(FATAL, "string %.20s ... too long to print", s);
824 	if (a[1]==nullstat) {
825 		printf("%s", s);
826 		return(true);
827 	}
828 	redirprint(s, (int)a[1], a[2]);
829 	return(false);
830 }
831 
832 obj nullproc() {}
833 
834 obj nodetoobj(a) node *a;
835 {
836 	obj x;
837 
838 	x.optr = (cell *) a->nobj;
839 	x.otype = OCELL;
840 	x.osub = a->subtype;
841 	if (isfld(x)) fldbld();
842 	return(x);
843 }
844 
845 redirprint(s, a, b) char *s; node *b;
846 {
847 	register int i;
848 	obj x;
849 
850 	x = execute(b);
851 	getsval(x.optr);
852 	for (i=0; i<FILENUM; i++)
853 		if (files[i].fp && strcmp(x.optr->sval, files[i].fname) == 0)
854 			goto doit;
855 	for (i=0; i<FILENUM; i++)
856 		if (files[i].fp == 0)
857 			break;
858 	if (i >= FILENUM)
859 		error(FATAL, "too many output files %d", i);
860 	if (a == '|')	/* a pipe! */
861 		files[i].fp = popen(x.optr->sval, "w");
862 	else if (a == APPEND)
863 		files[i].fp = fopen(x.optr->sval, "a");
864 	else
865 		files[i].fp = fopen(x.optr->sval, "w");
866 	if (files[i].fp == NULL)
867 		error(FATAL, "can't open file %s", x.optr->sval);
868 	files[i].fname = tostring(x.optr->sval);
869 doit:
870 	fprintf(files[i].fp, "%s", s);
871 #ifndef gcos
872 	fflush(files[i].fp);	/* in case someone is waiting for the output */
873 #endif
874 	tempfree(x);
875 }
876