xref: /csrg-svn/usr.bin/pascal/src/pcproc.c (revision 22216)
1*22216Sdist /*
2*22216Sdist  * Copyright (c) 1980 Regents of the University of California.
3*22216Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22216Sdist  * specifies the terms and conditions for redistribution.
5*22216Sdist  */
6766Speter 
715934Smckusick #ifndef lint
8*22216Sdist static char sccsid[] = "@(#)pcproc.c	5.1 (Berkeley) 06/05/85";
9*22216Sdist #endif not lint
10766Speter 
11766Speter #include "whoami.h"
12766Speter #ifdef PC
13766Speter     /*
14766Speter      * and to the end of the file
15766Speter      */
16766Speter #include "0.h"
17766Speter #include "tree.h"
1810372Speter #include "objfmt.h"
19766Speter #include "opcode.h"
2010372Speter #include "pc.h"
2118467Sralph #include <pcc.h>
2211333Speter #include "tmps.h"
2315934Smckusick #include "tree_ty.h"
24766Speter 
25766Speter /*
2611883Smckusick  * The constant EXPOSIZE specifies the number of digits in the exponent
2711883Smckusick  * of real numbers.
2811883Smckusick  *
299229Smckusick  * The constant REALSPC defines the amount of forced padding preceeding
309229Smckusick  * real numbers when they are printed. If REALSPC == 0, then no padding
319229Smckusick  * is added, REALSPC == 1 adds one extra blank irregardless of the width
329229Smckusick  * specified by the user.
339229Smckusick  *
349229Smckusick  * N.B. - Values greater than one require program mods.
359229Smckusick  */
3611883Smckusick #define EXPOSIZE	2
3711883Smckusick #define	REALSPC		0
389229Smckusick 
399229Smckusick /*
40766Speter  * The following array is used to determine which classes may be read
41766Speter  * from textfiles. It is indexed by the return value from classify.
42766Speter  */
43766Speter #define rdops(x) rdxxxx[(x)-(TFIRST)]
44766Speter 
45766Speter int rdxxxx[] = {
46766Speter 	0,		/* -7 file types */
47766Speter 	0,		/* -6 record types */
48766Speter 	0,		/* -5 array types */
49766Speter 	O_READE,	/* -4 scalar types */
50766Speter 	0,		/* -3 pointer types */
51766Speter 	0,		/* -2 set types */
52766Speter 	0,		/* -1 string types */
53766Speter 	0,		/*  0 nil, no type */
54766Speter 	O_READE,	/*  1 boolean */
55766Speter 	O_READC,	/*  2 character */
56766Speter 	O_READ4,	/*  3 integer */
57766Speter 	O_READ8		/*  4 real */
58766Speter };
59766Speter 
60766Speter /*
61766Speter  * Proc handles procedure calls.
62766Speter  * Non-builtin procedures are "buck-passed" to func (with a flag
63766Speter  * indicating that they are actually procedures.
64766Speter  * builtin procedures are handled here.
65766Speter  */
66766Speter pcproc(r)
6715934Smckusick 	struct tnode *r;	/* T_PCALL */
68766Speter {
69766Speter 	register struct nl *p;
7015934Smckusick 	register struct tnode *alv, *al;
7115934Smckusick 	register op;
72766Speter 	struct nl *filetype, *ap;
7315934Smckusick 	int argc, typ, fmtspec, strfmt;
7415934Smckusick 	struct tnode *argv, *file;
757967Smckusick 	char fmt, format[20], *strptr, *cmd;
7615934Smckusick 	int prec, field, strnglen, fmtstart;
7715934Smckusick 	char *pu;
7815934Smckusick 	struct tnode *pua, *pui, *puz;
79766Speter 	int i, j, k;
80766Speter 	int itemwidth;
813833Speter 	char		*readname;
823833Speter 	struct nl	*tempnlp;
833833Speter 	long		readtype;
843833Speter 	struct tmps	soffset;
8515935Smckusick 	bool		soffset_flag;
86766Speter 
87766Speter #define	CONPREC 4
88766Speter #define	VARPREC 8
89766Speter #define	CONWIDTH 1
90766Speter #define	VARWIDTH 2
91766Speter #define SKIP 16
92766Speter 
93766Speter 	/*
94766Speter 	 * Verify that the name is
95766Speter 	 * defined and is that of a
96766Speter 	 * procedure.
97766Speter 	 */
9815934Smckusick 	p = lookup(r->pcall_node.proc_id);
9915934Smckusick 	if (p == NLNIL) {
10015934Smckusick 		rvlist(r->pcall_node.arg);
101766Speter 		return;
102766Speter 	}
1031197Speter 	if (p->class != PROC && p->class != FPROC) {
104766Speter 		error("Can't call %s, its %s not a procedure", p->symbol, classes[p->class]);
10515934Smckusick 		rvlist(r->pcall_node.arg);
106766Speter 		return;
107766Speter 	}
10815934Smckusick 	argv = r->pcall_node.arg;
109766Speter 
110766Speter 	/*
111766Speter 	 * Call handles user defined
112766Speter 	 * procedures and functions.
113766Speter 	 */
114766Speter 	if (bn != 0) {
11515934Smckusick 		(void) call(p, argv, PROC, bn);
116766Speter 		return;
117766Speter 	}
118766Speter 
119766Speter 	/*
120766Speter 	 * Call to built-in procedure.
121766Speter 	 * Count the arguments.
122766Speter 	 */
123766Speter 	argc = 0;
12415934Smckusick 	for (al = argv; al != TR_NIL; al = al->list_node.next)
125766Speter 		argc++;
126766Speter 
127766Speter 	/*
128766Speter 	 * Switch on the operator
129766Speter 	 * associated with the built-in
130766Speter 	 * procedure in the namelist
131766Speter 	 */
132766Speter 	op = p->value[0] &~ NSTAND;
133766Speter 	if (opt('s') && (p->value[0] & NSTAND)) {
134766Speter 		standard();
135766Speter 		error("%s is a nonstandard procedure", p->symbol);
136766Speter 	}
137766Speter 	switch (op) {
138766Speter 
139766Speter 	case O_ABORT:
140766Speter 		if (argc != 0)
141766Speter 			error("null takes no arguments");
142766Speter 		return;
143766Speter 
144766Speter 	case O_FLUSH:
145766Speter 		if (argc == 0) {
14618467Sralph 			putleaf( PCC_ICON , 0 , 0 , PCCT_INT , "_PFLUSH" );
14718467Sralph 			putop( PCCOM_UNARY PCC_CALL , PCCT_INT );
148766Speter 			putdot( filename , line );
149766Speter 			return;
150766Speter 		}
151766Speter 		if (argc != 1) {
152766Speter 			error("flush takes at most one argument");
153766Speter 			return;
154766Speter 		}
15518467Sralph 		putleaf( PCC_ICON , 0 , 0
15618467Sralph 			, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
157766Speter 			, "_FLUSH" );
15815934Smckusick 		ap = stklval(argv->list_node.list, NOFLAGS);
15915934Smckusick 		if (ap == NLNIL)
160766Speter 			return;
161766Speter 		if (ap->class != FILET) {
162766Speter 			error("flush's argument must be a file, not %s", nameof(ap));
163766Speter 			return;
164766Speter 		}
16518467Sralph 		putop( PCC_CALL , PCCT_INT );
166766Speter 		putdot( filename , line );
167766Speter 		return;
168766Speter 
169766Speter 	case O_MESSAGE:
170766Speter 	case O_WRITEF:
171766Speter 	case O_WRITLN:
172766Speter 		/*
173766Speter 		 * Set up default file "output"'s type
174766Speter 		 */
175766Speter 		file = NIL;
176766Speter 		filetype = nl+T1CHAR;
177766Speter 		/*
178766Speter 		 * Determine the file implied
179766Speter 		 * for the write and generate
180766Speter 		 * code to make it the active file.
181766Speter 		 */
182766Speter 		if (op == O_MESSAGE) {
183766Speter 			/*
184766Speter 			 * For message, all that matters
185766Speter 			 * is that the filetype is
186766Speter 			 * a character file.
187766Speter 			 * Thus "output" will suit us fine.
188766Speter 			 */
18918467Sralph 			putleaf( PCC_ICON , 0 , 0 , PCCT_INT , "_PFLUSH" );
19018467Sralph 			putop( PCCOM_UNARY PCC_CALL , PCCT_INT );
191766Speter 			putdot( filename , line );
19215934Smckusick 			putRV( (char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
19318467Sralph 				PCCTM_PTR|PCCT_STRTY );
19418467Sralph 			putLV( "__err" , 0 , 0 , NGLOBAL , PCCTM_PTR|PCCT_STRTY );
19518467Sralph 			putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
196766Speter 			putdot( filename , line );
19715934Smckusick 		} else if (argv != TR_NIL && (al = argv->list_node.list)->tag !=
19815934Smckusick 					T_WEXP) {
199766Speter 			/*
200766Speter 			 * If there is a first argument which has
201766Speter 			 * no write widths, then it is potentially
202766Speter 			 * a file name.
203766Speter 			 */
204766Speter 			codeoff();
20515934Smckusick 			ap = stkrval(argv->list_node.list, NLNIL, (long) RREQ );
206766Speter 			codeon();
20715934Smckusick 			if (ap == NLNIL)
20815934Smckusick 				argv = argv->list_node.next;
209766Speter 			if (ap != NIL && ap->class == FILET) {
210766Speter 				/*
211766Speter 				 * Got "write(f, ...", make
212766Speter 				 * f the active file, and save
213766Speter 				 * it and its type for use in
214766Speter 				 * processing the rest of the
215766Speter 				 * arguments to write.
216766Speter 				 */
21715934Smckusick 				putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
21818467Sralph 					PCCTM_PTR|PCCT_STRTY );
21918467Sralph 				putleaf( PCC_ICON , 0 , 0
22018467Sralph 				    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
221766Speter 				    , "_UNIT" );
22215934Smckusick 				file = argv->list_node.list;
223766Speter 				filetype = ap->type;
22415934Smckusick 				(void) stklval(argv->list_node.list, NOFLAGS);
22518467Sralph 				putop( PCC_CALL , PCCT_INT );
22618467Sralph 				putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
227766Speter 				putdot( filename , line );
228766Speter 				/*
229766Speter 				 * Skip over the first argument
230766Speter 				 */
23115934Smckusick 				argv = argv->list_node.next;
232766Speter 				argc--;
233766Speter 			} else {
234766Speter 				/*
235766Speter 				 * Set up for writing on
236766Speter 				 * standard output.
237766Speter 				 */
23815934Smckusick 				putRV((char *) 0, cbn , CURFILEOFFSET ,
23918467Sralph 					NLOCAL , PCCTM_PTR|PCCT_STRTY );
2403833Speter 				putLV( "_output" , 0 , 0 , NGLOBAL ,
24118467Sralph 					PCCTM_PTR|PCCT_STRTY );
24218467Sralph 				putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
243766Speter 				putdot( filename , line );
2447954Speter 				output->nl_flags |= NUSED;
245766Speter 			}
246766Speter 		} else {
24715934Smckusick 			putRV((char *) 0, cbn , CURFILEOFFSET , NLOCAL ,
24818467Sralph 				PCCTM_PTR|PCCT_STRTY );
24918467Sralph 			putLV( "_output" , 0 , 0 , NGLOBAL , PCCTM_PTR|PCCT_STRTY );
25018467Sralph 			putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
251766Speter 			putdot( filename , line );
2527954Speter 			output->nl_flags |= NUSED;
253766Speter 		}
254766Speter 		/*
255766Speter 		 * Loop and process each
256766Speter 		 * of the arguments.
257766Speter 		 */
25815934Smckusick 		for (; argv != TR_NIL; argv = argv->list_node.next) {
25915935Smckusick 		        soffset_flag = FALSE;
260766Speter 			/*
261766Speter 			 * fmtspec indicates the type (CONstant or VARiable)
262766Speter 			 *	and number (none, WIDTH, and/or PRECision)
263766Speter 			 *	of the fields in the printf format for this
264766Speter 			 *	output variable.
265766Speter 			 * fmt is the format output indicator (D, E, F, O, X, S)
266766Speter 			 * fmtstart = 0 for leading blank; = 1 for no blank
267766Speter 			 */
268766Speter 			fmtspec = NIL;
269766Speter 			fmt = 'D';
270766Speter 			fmtstart = 1;
27115934Smckusick 			al = argv->list_node.list;
272766Speter 			if (al == NIL)
273766Speter 				continue;
27415934Smckusick 			if (al->tag == T_WEXP)
27515934Smckusick 				alv = al->wexpr_node.expr1;
276766Speter 			else
277766Speter 				alv = al;
27815934Smckusick 			if (alv == TR_NIL)
279766Speter 				continue;
280766Speter 			codeoff();
28115934Smckusick 			ap = stkrval(alv, NLNIL , (long) RREQ );
282766Speter 			codeon();
28315934Smckusick 			if (ap == NLNIL)
284766Speter 				continue;
285766Speter 			typ = classify(ap);
28615934Smckusick 			if (al->tag == T_WEXP) {
287766Speter 				/*
288766Speter 				 * Handle width expressions.
289766Speter 				 * The basic game here is that width
290766Speter 				 * expressions get evaluated. If they
291766Speter 				 * are constant, the value is placed
292766Speter 				 * directly in the format string.
293766Speter 				 * Otherwise the value is pushed onto
294766Speter 				 * the stack and an indirection is
295766Speter 				 * put into the format string.
296766Speter 				 */
29715934Smckusick 				if (al->wexpr_node.expr3 ==
29815934Smckusick 						(struct tnode *) OCT)
299766Speter 					fmt = 'O';
30015934Smckusick 				else if (al->wexpr_node.expr3 ==
30115934Smckusick 						(struct tnode *) HEX)
302766Speter 					fmt = 'X';
30315934Smckusick 				else if (al->wexpr_node.expr3 != TR_NIL) {
304766Speter 					/*
305766Speter 					 * Evaluate second format spec
306766Speter 					 */
30715934Smckusick 					if ( constval(al->wexpr_node.expr3)
308766Speter 					    && isa( con.ctype , "i" ) ) {
309766Speter 						fmtspec += CONPREC;
310766Speter 						prec = con.crval;
311766Speter 					} else {
312766Speter 						fmtspec += VARPREC;
313766Speter 					}
314766Speter 					fmt = 'f';
315766Speter 					switch ( typ ) {
316766Speter 					case TINT:
317766Speter 						if ( opt( 's' ) ) {
318766Speter 						    standard();
319766Speter 						    error("Writing %ss with two write widths is non-standard", clnames[typ]);
320766Speter 						}
321766Speter 						/* and fall through */
322766Speter 					case TDOUBLE:
323766Speter 						break;
324766Speter 					default:
325766Speter 						error("Cannot write %ss with two write widths", clnames[typ]);
326766Speter 						continue;
327766Speter 					}
328766Speter 				}
329766Speter 				/*
330766Speter 				 * Evaluate first format spec
331766Speter 				 */
33215934Smckusick 				if (al->wexpr_node.expr2 != TR_NIL) {
33315934Smckusick 					if ( constval(al->wexpr_node.expr2)
334766Speter 					    && isa( con.ctype , "i" ) ) {
335766Speter 						fmtspec += CONWIDTH;
336766Speter 						field = con.crval;
337766Speter 					} else {
338766Speter 						fmtspec += VARWIDTH;
339766Speter 					}
340766Speter 				}
341766Speter 				if ((fmtspec & CONPREC) && prec < 0 ||
342766Speter 				    (fmtspec & CONWIDTH) && field < 0) {
343766Speter 					error("Negative widths are not allowed");
344766Speter 					continue;
345766Speter 				}
3463180Smckusic 				if ( opt('s') &&
3473180Smckusic 				    ((fmtspec & CONPREC) && prec == 0 ||
3483180Smckusic 				    (fmtspec & CONWIDTH) && field == 0)) {
3493180Smckusic 					standard();
3503180Smckusic 					error("Zero widths are non-standard");
3513180Smckusic 				}
352766Speter 			}
353766Speter 			if (filetype != nl+T1CHAR) {
354766Speter 				if (fmt == 'O' || fmt == 'X') {
355766Speter 					error("Oct/hex allowed only on text files");
356766Speter 					continue;
357766Speter 				}
358766Speter 				if (fmtspec) {
359766Speter 					error("Write widths allowed only on text files");
360766Speter 					continue;
361766Speter 				}
362766Speter 				/*
363766Speter 				 * Generalized write, i.e.
364766Speter 				 * to a non-textfile.
365766Speter 				 */
36618467Sralph 				putleaf( PCC_ICON , 0 , 0
36718467Sralph 				    , (int) (PCCM_ADDTYPE(
36818467Sralph 					PCCM_ADDTYPE(
36918467Sralph 					    PCCM_ADDTYPE( p2type( filetype )
37018467Sralph 						    , PCCTM_PTR )
37118467Sralph 					    , PCCTM_FTN )
37218467Sralph 					, PCCTM_PTR ))
373766Speter 				    , "_FNIL" );
37415934Smckusick 				(void) stklval(file, NOFLAGS);
37518467Sralph 				putop( PCC_CALL
37618467Sralph 				    , PCCM_ADDTYPE( p2type( filetype ) , PCCTM_PTR ) );
37718467Sralph 				putop( PCCOM_UNARY PCC_MUL , p2type( filetype ) );
378766Speter 				/*
379766Speter 				 * file^ := ...
380766Speter 				 */
381766Speter 				switch ( classify( filetype ) ) {
382766Speter 				    case TBOOL:
383766Speter 				    case TCHAR:
384766Speter 				    case TINT:
385766Speter 				    case TSCAL:
3864589Speter 					precheck( filetype , "_RANG4"  , "_RSNG4" );
387766Speter 					    /* and fall through */
388766Speter 				    case TDOUBLE:
389766Speter 				    case TPTR:
39015934Smckusick 					ap = rvalue( argv->list_node.list , filetype , RREQ );
391766Speter 					break;
392766Speter 				    default:
39315934Smckusick 					ap = rvalue( argv->list_node.list , filetype , LREQ );
394766Speter 					break;
395766Speter 				}
396766Speter 				if (ap == NIL)
397766Speter 					continue;
39815934Smckusick 				if (incompat(ap, filetype, argv->list_node.list)) {
399766Speter 					cerror("Type mismatch in write to non-text file");
400766Speter 					continue;
401766Speter 				}
402766Speter 				switch ( classify( filetype ) ) {
403766Speter 				    case TBOOL:
404766Speter 				    case TCHAR:
405766Speter 				    case TINT:
406766Speter 				    case TSCAL:
40710373Speter 					    postcheck(filetype, ap);
40810373Speter 					    sconv(p2type(ap), p2type(filetype));
409766Speter 						/* and fall through */
410766Speter 				    case TDOUBLE:
411766Speter 				    case TPTR:
41218467Sralph 					    putop( PCC_ASSIGN , p2type( filetype ) );
413766Speter 					    putdot( filename , line );
414766Speter 					    break;
415766Speter 				    default:
41618467Sralph 					    putstrop(PCC_STASG,
41718467Sralph 						    PCCM_ADDTYPE(p2type(filetype),
41818467Sralph 							    PCCTM_PTR),
41915934Smckusick 						    (int) lwidth(filetype),
42011856Speter 						    align(filetype));
421766Speter 					    putdot( filename , line );
422766Speter 					    break;
423766Speter 				}
424766Speter 				/*
425766Speter 				 * put(file)
426766Speter 				 */
42718467Sralph 				putleaf( PCC_ICON , 0 , 0
42818467Sralph 				    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
429766Speter 				    , "_PUT" );
43015934Smckusick 				putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
43118467Sralph 					PCCTM_PTR|PCCT_STRTY );
43218467Sralph 				putop( PCC_CALL , PCCT_INT );
433766Speter 				putdot( filename , line );
434766Speter 				continue;
435766Speter 			}
436766Speter 			/*
437766Speter 			 * Write to a textfile
438766Speter 			 *
439766Speter 			 * Evaluate the expression
440766Speter 			 * to be written.
441766Speter 			 */
442766Speter 			if (fmt == 'O' || fmt == 'X') {
443766Speter 				if (opt('s')) {
444766Speter 					standard();
445766Speter 					error("Oct and hex are non-standard");
446766Speter 				}
447766Speter 				if (typ == TSTR || typ == TDOUBLE) {
448766Speter 					error("Can't write %ss with oct/hex", clnames[typ]);
449766Speter 					continue;
450766Speter 				}
451766Speter 				if (typ == TCHAR || typ == TBOOL)
452766Speter 					typ = TINT;
453766Speter 			}
454766Speter 			/*
455766Speter 			 * If there is no format specified by the programmer,
456766Speter 			 * implement the default.
457766Speter 			 */
458766Speter 			switch (typ) {
4596540Smckusick 			case TPTR:
4606540Smckusick 				warning();
4616540Smckusick 				if (opt('s')) {
4626540Smckusick 					standard();
4636540Smckusick 				}
4646540Smckusick 				error("Writing %ss to text files is non-standard",
4656540Smckusick 				    clnames[typ]);
4666540Smckusick 				/* and fall through */
467766Speter 			case TINT:
468766Speter 				if (fmt == 'f') {
469766Speter 					typ = TDOUBLE;
470766Speter 					goto tdouble;
471766Speter 				}
472766Speter 				if (fmtspec == NIL) {
473766Speter 					if (fmt == 'D')
474766Speter 						field = 10;
475766Speter 					else if (fmt == 'X')
476766Speter 						field = 8;
477766Speter 					else if (fmt == 'O')
478766Speter 						field = 11;
479766Speter 					else
480766Speter 						panic("fmt1");
481766Speter 					fmtspec = CONWIDTH;
482766Speter 				}
483766Speter 				break;
484766Speter 			case TCHAR:
485766Speter 			     tchar:
486766Speter 				fmt = 'c';
487766Speter 				break;
488766Speter 			case TSCAL:
4891629Speter 				warning();
490766Speter 				if (opt('s')) {
491766Speter 					standard();
492766Speter 				}
4936540Smckusick 				error("Writing %ss to text files is non-standard",
4946540Smckusick 				    clnames[typ]);
495766Speter 			case TBOOL:
496766Speter 				fmt = 's';
497766Speter 				break;
498766Speter 			case TDOUBLE:
499766Speter 			     tdouble:
500766Speter 				switch (fmtspec) {
501766Speter 				case NIL:
50211883Smckusick 					field = 14 + (5 + EXPOSIZE);
50311883Smckusick 				        prec = field - (5 + EXPOSIZE);
5043225Smckusic 					fmt = 'e';
505766Speter 					fmtspec = CONWIDTH + CONPREC;
506766Speter 					break;
507766Speter 				case CONWIDTH:
5089229Smckusick 					field -= REALSPC;
5099229Smckusick 					if (field < 1)
510766Speter 						field = 1;
51111883Smckusick 				        prec = field - (5 + EXPOSIZE);
512766Speter 					if (prec < 1)
513766Speter 						prec = 1;
514766Speter 					fmtspec += CONPREC;
5153225Smckusic 					fmt = 'e';
516766Speter 					break;
517766Speter 				case VARWIDTH:
518766Speter 					fmtspec += VARPREC;
5193225Smckusic 					fmt = 'e';
520766Speter 					break;
521766Speter 				case CONWIDTH + CONPREC:
522766Speter 				case CONWIDTH + VARPREC:
5239229Smckusick 					field -= REALSPC;
5249229Smckusick 					if (field < 1)
525766Speter 						field = 1;
526766Speter 				}
527766Speter 				format[0] = ' ';
5289229Smckusick 				fmtstart = 1 - REALSPC;
529766Speter 				break;
530766Speter 			case TSTR:
53115934Smckusick 				(void) constval( alv );
532766Speter 				switch ( classify( con.ctype ) ) {
533766Speter 				    case TCHAR:
534766Speter 					typ = TCHAR;
535766Speter 					goto tchar;
536766Speter 				    case TSTR:
537766Speter 					strptr = con.cpval;
538766Speter 					for (strnglen = 0;  *strptr++;  strnglen++) /* void */;
539766Speter 					strptr = con.cpval;
540766Speter 					break;
541766Speter 				    default:
542766Speter 					strnglen = width(ap);
543766Speter 					break;
544766Speter 				}
545766Speter 				fmt = 's';
546766Speter 				strfmt = fmtspec;
547766Speter 				if (fmtspec == NIL) {
548766Speter 					fmtspec = SKIP;
549766Speter 					break;
550766Speter 				}
551766Speter 				if (fmtspec & CONWIDTH) {
552766Speter 					if (field <= strnglen)
553766Speter 						fmtspec = SKIP;
554766Speter 					else
555766Speter 						field -= strnglen;
556766Speter 				}
557766Speter 				break;
558766Speter 			default:
559766Speter 				error("Can't write %ss to a text file", clnames[typ]);
560766Speter 				continue;
561766Speter 			}
562766Speter 			/*
563766Speter 			 * Generate the format string
564766Speter 			 */
565766Speter 			switch (fmtspec) {
566766Speter 			default:
567766Speter 				panic("fmt2");
568766Speter 			case NIL:
569766Speter 				if (fmt == 'c') {
570766Speter 					if ( opt( 't' ) ) {
57118467Sralph 					    putleaf( PCC_ICON , 0 , 0
57218467Sralph 						, PCCM_ADDTYPE( PCCTM_FTN|PCCT_INT , PCCTM_PTR )
573766Speter 						, "_WRITEC" );
57415934Smckusick 					    putRV((char *) 0 , cbn , CURFILEOFFSET ,
57518467Sralph 						    NLOCAL , PCCTM_PTR|PCCT_STRTY );
57615934Smckusick 					    (void) stkrval( alv , NLNIL , (long) RREQ );
57718467Sralph 					    putop( PCC_CM , PCCT_INT );
578766Speter 					} else {
57918467Sralph 					    putleaf( PCC_ICON , 0 , 0
58018467Sralph 						, PCCM_ADDTYPE( PCCTM_FTN|PCCT_INT , PCCTM_PTR )
581766Speter 						, "_fputc" );
58215934Smckusick 					    (void) stkrval( alv , NLNIL ,
58315934Smckusick 							(long) RREQ );
584766Speter 					}
58518467Sralph 					putleaf( PCC_ICON , 0 , 0
58618467Sralph 					    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
587766Speter 					    , "_ACTFILE" );
58815934Smckusick 					putRV((char *) 0, cbn , CURFILEOFFSET ,
58918467Sralph 						NLOCAL , PCCTM_PTR|PCCT_STRTY );
59018467Sralph 					putop( PCC_CALL , PCCT_INT );
59118467Sralph 					putop( PCC_CM , PCCT_INT );
59218467Sralph 					putop( PCC_CALL , PCCT_INT );
593766Speter 					putdot( filename , line );
594766Speter 				} else  {
595766Speter 					sprintf(&format[1], "%%%c", fmt);
596766Speter 					goto fmtgen;
597766Speter 				}
598766Speter 			case SKIP:
599766Speter 				break;
600766Speter 			case CONWIDTH:
601766Speter 				sprintf(&format[1], "%%%1D%c", field, fmt);
602766Speter 				goto fmtgen;
603766Speter 			case VARWIDTH:
604766Speter 				sprintf(&format[1], "%%*%c", fmt);
605766Speter 				goto fmtgen;
606766Speter 			case CONWIDTH + CONPREC:
607766Speter 				sprintf(&format[1], "%%%1D.%1D%c", field, prec, fmt);
608766Speter 				goto fmtgen;
609766Speter 			case CONWIDTH + VARPREC:
610766Speter 				sprintf(&format[1], "%%%1D.*%c", field, fmt);
611766Speter 				goto fmtgen;
612766Speter 			case VARWIDTH + CONPREC:
613766Speter 				sprintf(&format[1], "%%*.%1D%c", prec, fmt);
614766Speter 				goto fmtgen;
615766Speter 			case VARWIDTH + VARPREC:
616766Speter 				sprintf(&format[1], "%%*.*%c", fmt);
617766Speter 			fmtgen:
618766Speter 				if ( opt( 't' ) ) {
61918467Sralph 				    putleaf( PCC_ICON , 0 , 0
62018467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
621766Speter 					, "_WRITEF" );
62215934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
62318467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
62418467Sralph 				    putleaf( PCC_ICON , 0 , 0
62518467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
626766Speter 					, "_ACTFILE" );
62715934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
62818467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
62918467Sralph 				    putop( PCC_CALL , PCCT_INT );
63018467Sralph 				    putop( PCC_CM , PCCT_INT );
631766Speter 				} else {
63218467Sralph 				    putleaf( PCC_ICON , 0 , 0
63318467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
634766Speter 					, "_fprintf" );
63518467Sralph 				    putleaf( PCC_ICON , 0 , 0
63618467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
637766Speter 					, "_ACTFILE" );
63815934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
63918467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
64018467Sralph 				    putop( PCC_CALL , PCCT_INT );
641766Speter 				}
642766Speter 				putCONG( &format[ fmtstart ]
643766Speter 					, strlen( &format[ fmtstart ] )
644766Speter 					, LREQ );
64518467Sralph 				putop( PCC_CM , PCCT_INT );
646766Speter 				if ( fmtspec & VARWIDTH ) {
647766Speter 					/*
648766Speter 					 * either
649766Speter 					 *	,(temp=width,MAX(temp,...)),
650766Speter 					 * or
651766Speter 					 *	, MAX( width , ... ) ,
652766Speter 					 */
65315934Smckusick 				    if ( ( typ == TDOUBLE &&
65415934Smckusick 						al->wexpr_node.expr3 == TR_NIL )
655766Speter 					|| typ == TSTR ) {
65615935Smckusick 					soffset_flag = TRUE;
6573225Smckusic 					soffset = sizes[cbn].curtmps;
65815934Smckusick 					tempnlp = tmpalloc((long) (sizeof(long)),
6593225Smckusic 						nl+T4INT, REGOK);
66015934Smckusick 					putRV((char *) 0 , cbn ,
6613833Speter 					    tempnlp -> value[ NL_OFFS ] ,
66218467Sralph 					    tempnlp -> extra_flags , PCCT_INT );
66315934Smckusick 					ap = stkrval( al->wexpr_node.expr2 ,
66415934Smckusick 						NLNIL , (long) RREQ );
66518467Sralph 					putop( PCC_ASSIGN , PCCT_INT );
66618467Sralph 					putleaf( PCC_ICON , 0 , 0
66718467Sralph 					    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
668766Speter 					    , "_MAX" );
66915934Smckusick 					putRV((char *) 0 , cbn ,
6703833Speter 					    tempnlp -> value[ NL_OFFS ] ,
67118467Sralph 					    tempnlp -> extra_flags , PCCT_INT );
672766Speter 				    } else {
673766Speter 					if (opt('t')
674766Speter 					    || typ == TSTR || typ == TDOUBLE) {
67518467Sralph 					    putleaf( PCC_ICON , 0 , 0
67618467Sralph 						,PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT, PCCTM_PTR )
677766Speter 						,"_MAX" );
678766Speter 					}
67915934Smckusick 					ap = stkrval( al->wexpr_node.expr2,
68015934Smckusick 						NLNIL , (long) RREQ );
681766Speter 				    }
68215934Smckusick 				    if (ap == NLNIL)
683766Speter 					    continue;
684766Speter 				    if (isnta(ap,"i")) {
685766Speter 					    error("First write width must be integer, not %s", nameof(ap));
686766Speter 					    continue;
687766Speter 				    }
688766Speter 				    switch ( typ ) {
689766Speter 				    case TDOUBLE:
69018467Sralph 					putleaf( PCC_ICON , REALSPC , 0 , PCCT_INT , (char *) 0 );
69118467Sralph 					putop( PCC_CM , PCCT_INT );
69218467Sralph 					putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 );
69318467Sralph 					putop( PCC_CM , PCCT_INT );
69418467Sralph 					putop( PCC_CALL , PCCT_INT );
69515934Smckusick 					if ( al->wexpr_node.expr3 == TR_NIL ) {
696766Speter 						/*
697766Speter 						 * finish up the comma op
698766Speter 						 */
69918467Sralph 					    putop( PCC_COMOP , PCCT_INT );
700766Speter 					    fmtspec &= ~VARPREC;
70118467Sralph 					    putop( PCC_CM , PCCT_INT );
70218467Sralph 					    putleaf( PCC_ICON , 0 , 0
70318467Sralph 						, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
704766Speter 						, "_MAX" );
70515934Smckusick 					    putRV((char *) 0 , cbn ,
7063833Speter 						tempnlp -> value[ NL_OFFS ] ,
7073833Speter 						tempnlp -> extra_flags ,
70818467Sralph 						PCCT_INT );
70918467Sralph 					    putleaf( PCC_ICON ,
71011883Smckusick 						5 + EXPOSIZE + REALSPC ,
71118467Sralph 						0 , PCCT_INT , (char *) 0 );
71218467Sralph 					    putop( PCC_CM , PCCT_INT );
71318467Sralph 					    putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 );
71418467Sralph 					    putop( PCC_CM , PCCT_INT );
71518467Sralph 					    putop( PCC_CALL , PCCT_INT );
716766Speter 					}
71718467Sralph 					putop( PCC_CM , PCCT_INT );
718766Speter 					break;
719766Speter 				    case TSTR:
72018467Sralph 					putleaf( PCC_ICON , strnglen , 0 , PCCT_INT , (char *) 0 );
72118467Sralph 					putop( PCC_CM , PCCT_INT );
72218467Sralph 					putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
72318467Sralph 					putop( PCC_CM , PCCT_INT );
72418467Sralph 					putop( PCC_CALL , PCCT_INT );
72518467Sralph 					putop( PCC_COMOP , PCCT_INT );
72618467Sralph 					putop( PCC_CM , PCCT_INT );
727766Speter 					break;
728766Speter 				    default:
729766Speter 					if (opt('t')) {
73018467Sralph 					    putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
73118467Sralph 					    putop( PCC_CM , PCCT_INT );
73218467Sralph 					    putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
73318467Sralph 					    putop( PCC_CM , PCCT_INT );
73418467Sralph 					    putop( PCC_CALL , PCCT_INT );
735766Speter 					}
73618467Sralph 					putop( PCC_CM , PCCT_INT );
737766Speter 					break;
738766Speter 				    }
739766Speter 				}
740766Speter 				/*
741766Speter 				 * If there is a variable precision,
742766Speter 				 * evaluate it
743766Speter 				 */
744766Speter 				if (fmtspec & VARPREC) {
745766Speter 					if (opt('t')) {
74618467Sralph 					putleaf( PCC_ICON , 0 , 0
74718467Sralph 					    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
748766Speter 					    , "_MAX" );
749766Speter 					}
75015934Smckusick 					ap = stkrval( al->wexpr_node.expr3 ,
75115934Smckusick 						NLNIL , (long) RREQ );
752766Speter 					if (ap == NIL)
753766Speter 						continue;
754766Speter 					if (isnta(ap,"i")) {
755766Speter 						error("Second write width must be integer, not %s", nameof(ap));
756766Speter 						continue;
757766Speter 					}
758766Speter 					if (opt('t')) {
75918467Sralph 					    putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
76018467Sralph 					    putop( PCC_CM , PCCT_INT );
76118467Sralph 					    putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
76218467Sralph 					    putop( PCC_CM , PCCT_INT );
76318467Sralph 					    putop( PCC_CALL , PCCT_INT );
764766Speter 					}
76518467Sralph 				 	putop( PCC_CM , PCCT_INT );
766766Speter 				}
767766Speter 				/*
768766Speter 				 * evaluate the thing we want printed.
769766Speter 				 */
770766Speter 				switch ( typ ) {
7716540Smckusick 				case TPTR:
772766Speter 				case TCHAR:
773766Speter 				case TINT:
77415934Smckusick 				    (void) stkrval( alv , NLNIL , (long) RREQ );
77518467Sralph 				    putop( PCC_CM , PCCT_INT );
776766Speter 				    break;
777766Speter 				case TDOUBLE:
77815934Smckusick 				    ap = stkrval( alv , NLNIL , (long) RREQ );
77910373Speter 				    if (isnta(ap, "d")) {
78018467Sralph 					sconv(p2type(ap), PCCT_DOUBLE);
781766Speter 				    }
78218467Sralph 				    putop( PCC_CM , PCCT_INT );
783766Speter 				    break;
784766Speter 				case TSCAL:
785766Speter 				case TBOOL:
78618467Sralph 				    putleaf( PCC_ICON , 0 , 0
78718467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
788766Speter 					, "_NAM" );
78915934Smckusick 				    ap = stkrval( alv , NLNIL , (long) RREQ );
790766Speter 				    sprintf( format , PREFIXFORMAT , LABELPREFIX
791766Speter 					    , listnames( ap ) );
79218467Sralph 				    putleaf( PCC_ICON , 0 , 0 ,
79318467Sralph 					(int) (PCCTM_PTR | PCCT_CHAR), format );
79418467Sralph 				    putop( PCC_CM , PCCT_INT );
79518467Sralph 				    putop( PCC_CALL , PCCT_INT );
79618467Sralph 				    putop( PCC_CM , PCCT_INT );
797766Speter 				    break;
798766Speter 				case TSTR:
799766Speter 				    putCONG( "" , 0 , LREQ );
80018467Sralph 				    putop( PCC_CM , PCCT_INT );
801766Speter 				    break;
8026540Smckusick 				default:
8036540Smckusick 				    panic("fmt3");
8046540Smckusick 				    break;
805766Speter 				}
80618467Sralph 				putop( PCC_CALL , PCCT_INT );
807766Speter 				putdot( filename , line );
808766Speter 			}
809766Speter 			/*
810766Speter 			 * Write the string after its blank padding
811766Speter 			 */
812766Speter 			if (typ == TSTR ) {
813766Speter 				if ( opt( 't' ) ) {
81418467Sralph 				    putleaf( PCC_ICON , 0 , 0
81518467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
816766Speter 					, "_WRITES" );
81715934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
81818467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
81915934Smckusick 				    ap = stkrval(alv, NLNIL , (long) RREQ );
82018467Sralph 				    putop( PCC_CM , PCCT_INT );
821766Speter 				} else {
82218467Sralph 				    putleaf( PCC_ICON , 0 , 0
82318467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
824766Speter 					, "_fwrite" );
82515934Smckusick 				    ap = stkrval(alv, NLNIL , (long) RREQ );
826766Speter 				}
827766Speter 				if (strfmt & VARWIDTH) {
828766Speter 					    /*
829766Speter 					     *	min, inline expanded as
830766Speter 					     *	temp < len ? temp : len
831766Speter 					     */
83215934Smckusick 					putRV((char *) 0 , cbn ,
8333833Speter 					    tempnlp -> value[ NL_OFFS ] ,
83418467Sralph 					    tempnlp -> extra_flags , PCCT_INT );
83518467Sralph 					putleaf( PCC_ICON , strnglen , 0 , PCCT_INT , (char *) 0 );
83618467Sralph 					putop( PCC_LT , PCCT_INT );
83715934Smckusick 					putRV((char *) 0 , cbn ,
8383833Speter 					    tempnlp -> value[ NL_OFFS ] ,
83918467Sralph 					    tempnlp -> extra_flags , PCCT_INT );
84018467Sralph 					putleaf( PCC_ICON , strnglen , 0 , PCCT_INT , (char *) 0 );
84118467Sralph 					putop( PCC_COLON , PCCT_INT );
84218467Sralph 					putop( PCC_QUEST , PCCT_INT );
843766Speter 				} else {
844766Speter 					if (   ( fmtspec & SKIP )
845766Speter 					    && ( strfmt & CONWIDTH ) ) {
846766Speter 						strnglen = field;
847766Speter 					}
84818467Sralph 					putleaf( PCC_ICON , strnglen , 0 , PCCT_INT , (char *) 0 );
849766Speter 				}
85018467Sralph 				putop( PCC_CM , PCCT_INT );
85118467Sralph 				putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 );
85218467Sralph 				putop( PCC_CM , PCCT_INT );
85318467Sralph 				putleaf( PCC_ICON , 0 , 0
85418467Sralph 				    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
855766Speter 				    , "_ACTFILE" );
85615934Smckusick 				putRV((char *) 0, cbn , CURFILEOFFSET , NLOCAL ,
85718467Sralph 					PCCTM_PTR|PCCT_STRTY );
85818467Sralph 				putop( PCC_CALL , PCCT_INT );
85918467Sralph 				putop( PCC_CM , PCCT_INT );
86018467Sralph 				putop( PCC_CALL , PCCT_INT );
861766Speter 				putdot( filename , line );
862766Speter 			}
86315935Smckusick 			if (soffset_flag) {
86415935Smckusick 				tmpfree(&soffset);
86515935Smckusick 				soffset_flag = FALSE;
86615935Smckusick 			}
867766Speter 		}
868766Speter 		/*
869766Speter 		 * Done with arguments.
870766Speter 		 * Handle writeln and
871766Speter 		 * insufficent number of args.
872766Speter 		 */
873766Speter 		switch (p->value[0] &~ NSTAND) {
874766Speter 			case O_WRITEF:
875766Speter 				if (argc == 0)
876766Speter 					error("Write requires an argument");
877766Speter 				break;
878766Speter 			case O_MESSAGE:
879766Speter 				if (argc == 0)
880766Speter 					error("Message requires an argument");
881766Speter 			case O_WRITLN:
882766Speter 				if (filetype != nl+T1CHAR)
883766Speter 					error("Can't 'writeln' a non text file");
884766Speter 				if ( opt( 't' ) ) {
88518467Sralph 				    putleaf( PCC_ICON , 0 , 0
88618467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
887766Speter 					, "_WRITLN" );
88815934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
88918467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
890766Speter 				} else {
89118467Sralph 				    putleaf( PCC_ICON , 0 , 0
89218467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
893766Speter 					, "_fputc" );
89418467Sralph 				    putleaf( PCC_ICON , '\n' , 0 , (int) PCCT_CHAR , (char *) 0 );
89518467Sralph 				    putleaf( PCC_ICON , 0 , 0
89618467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
897766Speter 					, "_ACTFILE" );
89815934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
89918467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
90018467Sralph 				    putop( PCC_CALL , PCCT_INT );
90118467Sralph 				    putop( PCC_CM , PCCT_INT );
902766Speter 				}
90318467Sralph 				putop( PCC_CALL , PCCT_INT );
904766Speter 				putdot( filename , line );
905766Speter 				break;
906766Speter 		}
907766Speter 		return;
908766Speter 
909766Speter 	case O_READ4:
910766Speter 	case O_READLN:
911766Speter 		/*
912766Speter 		 * Set up default
913766Speter 		 * file "input".
914766Speter 		 */
915766Speter 		file = NIL;
916766Speter 		filetype = nl+T1CHAR;
917766Speter 		/*
918766Speter 		 * Determine the file implied
919766Speter 		 * for the read and generate
920766Speter 		 * code to make it the active file.
921766Speter 		 */
92215934Smckusick 		if (argv != TR_NIL) {
923766Speter 			codeoff();
92415934Smckusick 			ap = stkrval(argv->list_node.list, NLNIL, (long) RREQ );
925766Speter 			codeon();
92615934Smckusick 			if (ap == NLNIL)
92715934Smckusick 				argv = argv->list_node.next;
92815934Smckusick 			if (ap != NLNIL && ap->class == FILET) {
929766Speter 				/*
930766Speter 				 * Got "read(f, ...", make
931766Speter 				 * f the active file, and save
932766Speter 				 * it and its type for use in
933766Speter 				 * processing the rest of the
934766Speter 				 * arguments to read.
935766Speter 				 */
93615934Smckusick 				file = argv->list_node.list;
937766Speter 				filetype = ap->type;
93815934Smckusick 				putRV((char *) 0, cbn , CURFILEOFFSET , NLOCAL ,
93918467Sralph 					PCCTM_PTR|PCCT_STRTY );
94018467Sralph 				putleaf( PCC_ICON , 0 , 0
94118467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
942766Speter 					, "_UNIT" );
94315934Smckusick 				(void) stklval(argv->list_node.list, NOFLAGS);
94418467Sralph 				putop( PCC_CALL , PCCT_INT );
94518467Sralph 				putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
946766Speter 				putdot( filename , line );
94715934Smckusick 				argv = argv->list_node.next;
948766Speter 				argc--;
949766Speter 			} else {
950766Speter 				/*
951766Speter 				 * Default is read from
952766Speter 				 * standard input.
953766Speter 				 */
95415934Smckusick 				putRV((char *) 0, cbn , CURFILEOFFSET , NLOCAL ,
95518467Sralph 					PCCTM_PTR|PCCT_STRTY );
9563833Speter 				putLV( "_input" , 0 , 0 , NGLOBAL ,
95718467Sralph 					PCCTM_PTR|PCCT_STRTY );
95818467Sralph 				putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
959766Speter 				putdot( filename , line );
960766Speter 				input->nl_flags |= NUSED;
961766Speter 			}
962766Speter 		} else {
96315934Smckusick 			putRV((char *) 0, cbn , CURFILEOFFSET , NLOCAL ,
96418467Sralph 				PCCTM_PTR|PCCT_STRTY );
96518467Sralph 			putLV( "_input" , 0 , 0 , NGLOBAL , PCCTM_PTR|PCCT_STRTY );
96618467Sralph 			putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
967766Speter 			putdot( filename , line );
968766Speter 			input->nl_flags |= NUSED;
969766Speter 		}
970766Speter 		/*
971766Speter 		 * Loop and process each
972766Speter 		 * of the arguments.
973766Speter 		 */
97415934Smckusick 		for (; argv != TR_NIL; argv = argv->list_node.next) {
975766Speter 			/*
976766Speter 			 * Get the address of the target
977766Speter 			 * on the stack.
978766Speter 			 */
97915934Smckusick 			al = argv->list_node.list;
98015934Smckusick 			if (al == TR_NIL)
981766Speter 				continue;
98215934Smckusick 			if (al->tag != T_VAR) {
983766Speter 				error("Arguments to %s must be variables, not expressions", p->symbol);
984766Speter 				continue;
985766Speter 			}
986766Speter 			codeoff();
987766Speter 			ap = stklval(al, MOD|ASGN|NOUSE);
988766Speter 			codeon();
98915934Smckusick 			if (ap == NLNIL)
990766Speter 				continue;
991766Speter 			if (filetype != nl+T1CHAR) {
992766Speter 				/*
993766Speter 				 * Generalized read, i.e.
994766Speter 				 * from a non-textfile.
995766Speter 				 */
99615934Smckusick 				if (incompat(filetype, ap, argv->list_node.list )) {
997766Speter 					error("Type mismatch in read from non-text file");
998766Speter 					continue;
999766Speter 				}
1000766Speter 				/*
1001766Speter 				 * var := file ^;
1002766Speter 				 */
1003766Speter 				ap = lvalue( al , MOD | ASGN | NOUSE , RREQ );
1004766Speter 				if ( isa( ap , "bsci" ) ) {
1005766Speter 					precheck( ap , "_RANG4" , "_RSNG4" );
1006766Speter 				}
100718467Sralph 				putleaf( PCC_ICON , 0 , 0
100818467Sralph 				    , (int) (PCCM_ADDTYPE(
100918467Sralph 					PCCM_ADDTYPE(
101018467Sralph 					    PCCM_ADDTYPE(
101118467Sralph 						p2type( filetype ) , PCCTM_PTR )
101218467Sralph 					    , PCCTM_FTN )
101318467Sralph 					, PCCTM_PTR ))
1014766Speter 				    , "_FNIL" );
1015766Speter 				if (file != NIL)
101615934Smckusick 					(void) stklval(file, NOFLAGS);
1017766Speter 				else /* Magic */
10183833Speter 					putRV( "_input" , 0 , 0 , NGLOBAL ,
101918467Sralph 						PCCTM_PTR | PCCT_STRTY );
102018467Sralph 				putop(PCC_CALL, PCCM_ADDTYPE(p2type(filetype), PCCTM_PTR));
1021766Speter 				switch ( classify( filetype ) ) {
1022766Speter 				    case TBOOL:
1023766Speter 				    case TCHAR:
1024766Speter 				    case TINT:
1025766Speter 				    case TSCAL:
1026766Speter 				    case TDOUBLE:
1027766Speter 				    case TPTR:
102818467Sralph 					putop( PCCOM_UNARY PCC_MUL
1029766Speter 						, p2type( filetype ) );
1030766Speter 				}
1031766Speter 				switch ( classify( filetype ) ) {
1032766Speter 				    case TBOOL:
1033766Speter 				    case TCHAR:
1034766Speter 				    case TINT:
1035766Speter 				    case TSCAL:
103610373Speter 					    postcheck(ap, filetype);
103710373Speter 					    sconv(p2type(filetype), p2type(ap));
1038766Speter 						/* and fall through */
1039766Speter 				    case TDOUBLE:
1040766Speter 				    case TPTR:
104118467Sralph 					    putop( PCC_ASSIGN , p2type( ap ) );
1042766Speter 					    putdot( filename , line );
1043766Speter 					    break;
1044766Speter 				    default:
104518467Sralph 					    putstrop(PCC_STASG,
104618467Sralph 						    PCCM_ADDTYPE(p2type(ap), PCCTM_PTR),
104715934Smckusick 						    (int) lwidth(ap),
104811856Speter 						    align(ap));
1049766Speter 					    putdot( filename , line );
1050766Speter 					    break;
1051766Speter 				}
1052766Speter 				/*
1053766Speter 				 * get(file);
1054766Speter 				 */
105518467Sralph 				putleaf( PCC_ICON , 0 , 0
105618467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1057766Speter 					, "_GET" );
105815934Smckusick 				putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
105918467Sralph 					PCCTM_PTR|PCCT_STRTY );
106018467Sralph 				putop( PCC_CALL , PCCT_INT );
1061766Speter 				putdot( filename , line );
1062766Speter 				continue;
1063766Speter 			}
1064766Speter 			    /*
1065766Speter 			     *	if you get to here, you are reading from
1066766Speter 			     *	a text file.  only possiblities are:
1067766Speter 			     *	character, integer, real, or scalar.
1068766Speter 			     *	read( f , foo , ... ) is done as
1069766Speter 			     *	foo := read( f ) with rangechecking
1070766Speter 			     *	if appropriate.
1071766Speter 			     */
1072766Speter 			typ = classify(ap);
1073766Speter 			op = rdops(typ);
1074766Speter 			if (op == NIL) {
1075766Speter 				error("Can't read %ss from a text file", clnames[typ]);
1076766Speter 				continue;
1077766Speter 			}
1078766Speter 			    /*
1079766Speter 			     *	left hand side of foo := read( f )
1080766Speter 			     */
1081766Speter 			ap = lvalue( al , MOD|ASGN|NOUSE , RREQ );
1082766Speter 			if ( isa( ap , "bsci" ) ) {
1083766Speter 			    precheck( ap , "_RANG4" , "_RSNG4" );
1084766Speter 			}
1085766Speter 			switch ( op ) {
1086766Speter 			    case O_READC:
1087766Speter 				readname = "_READC";
108818467Sralph 				readtype = PCCT_INT;
1089766Speter 				break;
1090766Speter 			    case O_READ4:
1091766Speter 				readname = "_READ4";
109218467Sralph 				readtype = PCCT_INT;
1093766Speter 				break;
1094766Speter 			    case O_READ8:
1095766Speter 				readname = "_READ8";
109618467Sralph 				readtype = PCCT_DOUBLE;
1097766Speter 				break;
1098766Speter 			    case O_READE:
1099766Speter 				readname = "_READE";
110018467Sralph 				readtype = PCCT_INT;
1101766Speter 				break;
1102766Speter 			}
110318467Sralph 			putleaf( PCC_ICON , 0 , 0
110418467Sralph 				, (int) PCCM_ADDTYPE( PCCTM_FTN | readtype , PCCTM_PTR )
1105766Speter 				, readname );
110615934Smckusick 			putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
110718467Sralph 				PCCTM_PTR|PCCT_STRTY );
1108766Speter 			if ( op == O_READE ) {
1109766Speter 				sprintf( format , PREFIXFORMAT , LABELPREFIX
1110766Speter 					, listnames( ap ) );
111118467Sralph 				putleaf( PCC_ICON , 0, 0, (int) (PCCTM_PTR | PCCT_CHAR),
111215934Smckusick 					format );
111318467Sralph 				putop( PCC_CM , PCCT_INT );
11141629Speter 				warning();
1115766Speter 				if (opt('s')) {
1116766Speter 					standard();
1117766Speter 				}
11181629Speter 				error("Reading scalars from text files is non-standard");
1119766Speter 			}
112018467Sralph 			putop( PCC_CALL , (int) readtype );
1121766Speter 			if ( isa( ap , "bcsi" ) ) {
112218467Sralph 			    postcheck(ap, readtype==PCCT_INT?nl+T4INT:nl+TDOUBLE);
1123766Speter 			}
112415934Smckusick 			sconv((int) readtype, p2type(ap));
112518467Sralph 			putop( PCC_ASSIGN , p2type( ap ) );
1126766Speter 			putdot( filename , line );
1127766Speter 		}
1128766Speter 		/*
1129766Speter 		 * Done with arguments.
1130766Speter 		 * Handle readln and
1131766Speter 		 * insufficient number of args.
1132766Speter 		 */
1133766Speter 		if (p->value[0] == O_READLN) {
1134766Speter 			if (filetype != nl+T1CHAR)
1135766Speter 				error("Can't 'readln' a non text file");
113618467Sralph 			putleaf( PCC_ICON , 0 , 0
113718467Sralph 				, (int) PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1138766Speter 				, "_READLN" );
113915934Smckusick 			putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
114018467Sralph 				PCCTM_PTR|PCCT_STRTY );
114118467Sralph 			putop( PCC_CALL , PCCT_INT );
1142766Speter 			putdot( filename , line );
1143766Speter 		} else if (argc == 0)
1144766Speter 			error("read requires an argument");
1145766Speter 		return;
1146766Speter 
1147766Speter 	case O_GET:
1148766Speter 	case O_PUT:
1149766Speter 		if (argc != 1) {
1150766Speter 			error("%s expects one argument", p->symbol);
1151766Speter 			return;
1152766Speter 		}
115318467Sralph 		putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
115418467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1155766Speter 			, "_UNIT" );
115615934Smckusick 		ap = stklval(argv->list_node.list, NOFLAGS);
115715934Smckusick 		if (ap == NLNIL)
1158766Speter 			return;
1159766Speter 		if (ap->class != FILET) {
1160766Speter 			error("Argument to %s must be a file, not %s", p->symbol, nameof(ap));
1161766Speter 			return;
1162766Speter 		}
116318467Sralph 		putop( PCC_CALL , PCCT_INT );
116418467Sralph 		putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
1165766Speter 		putdot( filename , line );
116618467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1167766Speter 			, op == O_GET ? "_GET" : "_PUT" );
116818467Sralph 		putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
116918467Sralph 		putop( PCC_CALL , PCCT_INT );
1170766Speter 		putdot( filename , line );
1171766Speter 		return;
1172766Speter 
1173766Speter 	case O_RESET:
1174766Speter 	case O_REWRITE:
1175766Speter 		if (argc == 0 || argc > 2) {
1176766Speter 			error("%s expects one or two arguments", p->symbol);
1177766Speter 			return;
1178766Speter 		}
1179766Speter 		if (opt('s') && argc == 2) {
1180766Speter 			standard();
1181766Speter 			error("Two argument forms of reset and rewrite are non-standard");
1182766Speter 		}
118318467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCT_INT
1184766Speter 			, op == O_RESET ? "_RESET" : "_REWRITE" );
118515934Smckusick 		ap = stklval(argv->list_node.list, MOD|NOUSE);
118615934Smckusick 		if (ap == NLNIL)
1187766Speter 			return;
1188766Speter 		if (ap->class != FILET) {
1189766Speter 			error("First argument to %s must be a file, not %s", p->symbol, nameof(ap));
1190766Speter 			return;
1191766Speter 		}
1192766Speter 		if (argc == 2) {
1193766Speter 			/*
1194766Speter 			 * Optional second argument
1195766Speter 			 * is a string name of a
1196766Speter 			 * UNIX (R) file to be associated.
1197766Speter 			 */
119815934Smckusick 			al = argv->list_node.next;
119915934Smckusick 			al = (struct tnode *) stkrval(al->list_node.list,
120015934Smckusick 					NLNIL , (long) RREQ );
120115934Smckusick 			if (al == TR_NIL)
1202766Speter 				return;
120315934Smckusick 			if (classify((struct nl *) al) != TSTR) {
120415934Smckusick 				error("Second argument to %s must be a string, not %s", p->symbol, nameof((struct nl *) al));
1205766Speter 				return;
1206766Speter 			}
120715934Smckusick 			strnglen = width((struct nl *) al);
1208766Speter 		} else {
120918467Sralph 			putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
1210766Speter 			strnglen = 0;
1211766Speter 		}
121218467Sralph 		putop( PCC_CM , PCCT_INT );
121318467Sralph 		putleaf( PCC_ICON , strnglen , 0 , PCCT_INT , (char *) 0 );
121418467Sralph 		putop( PCC_CM , PCCT_INT );
121518467Sralph 		putleaf( PCC_ICON , text(ap) ? 0: width(ap->type) , 0 , PCCT_INT , (char *) 0 );
121618467Sralph 		putop( PCC_CM , PCCT_INT );
121718467Sralph 		putop( PCC_CALL , PCCT_INT );
1218766Speter 		putdot( filename , line );
1219766Speter 		return;
1220766Speter 
1221766Speter 	case O_NEW:
1222766Speter 	case O_DISPOSE:
1223766Speter 		if (argc == 0) {
1224766Speter 			error("%s expects at least one argument", p->symbol);
1225766Speter 			return;
1226766Speter 		}
122715934Smckusick 		alv = argv->list_node.list;
12287967Smckusick 		codeoff();
12299139Smckusick 		ap = stklval(alv, op == O_NEW ? ( MOD | NOUSE ) : MOD );
12307967Smckusick 		codeon();
123115934Smckusick 		if (ap == NLNIL)
1232766Speter 			return;
1233766Speter 		if (ap->class != PTR) {
1234766Speter 			error("(First) argument to %s must be a pointer, not %s", p->symbol, nameof(ap));
1235766Speter 			return;
1236766Speter 		}
1237766Speter 		ap = ap->type;
123815934Smckusick 		if (ap == NLNIL)
1239766Speter 			return;
12409139Smckusick 		if (op == O_NEW)
12419139Smckusick 			cmd = "_NEW";
12429139Smckusick 		else /* op == O_DISPOSE */
12437967Smckusick 			if ((ap->nl_flags & NFILES) != 0)
12447967Smckusick 				cmd = "_DFDISPOSE";
12457967Smckusick 			else
12467967Smckusick 				cmd = "_DISPOSE";
124718467Sralph 		putleaf( PCC_ICON, 0, 0, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ), cmd);
124815934Smckusick 		(void) stklval(alv, op == O_NEW ? ( MOD | NOUSE ) : MOD );
124915934Smckusick 		argv = argv->list_node.next;
125015934Smckusick 		if (argv != TR_NIL) {
1251766Speter 			if (ap->class != RECORD) {
1252766Speter 				error("Record required when specifying variant tags");
1253766Speter 				return;
1254766Speter 			}
125515934Smckusick 			for (; argv != TR_NIL; argv = argv->list_node.next) {
1256766Speter 				if (ap->ptr[NL_VARNT] == NIL) {
1257766Speter 					error("Too many tag fields");
1258766Speter 					return;
1259766Speter 				}
126015934Smckusick 				if (!isconst(argv->list_node.list)) {
1261766Speter 					error("Second and successive arguments to %s must be constants", p->symbol);
1262766Speter 					return;
1263766Speter 				}
126415934Smckusick 				gconst(argv->list_node.list);
1265766Speter 				if (con.ctype == NIL)
1266766Speter 					return;
126715934Smckusick 				if (incompat(con.ctype, (ap->ptr[NL_TAG])->type , TR_NIL )) {
1268766Speter 					cerror("Specified tag constant type clashed with variant case selector type");
1269766Speter 					return;
1270766Speter 				}
1271766Speter 				for (ap = ap->ptr[NL_VARNT]; ap != NIL; ap = ap->chain)
1272766Speter 					if (ap->range[0] == con.crval)
1273766Speter 						break;
1274766Speter 				if (ap == NIL) {
1275766Speter 					error("No variant case label value equals specified constant value");
1276766Speter 					return;
1277766Speter 				}
1278766Speter 				ap = ap->ptr[NL_VTOREC];
1279766Speter 			}
1280766Speter 		}
128118467Sralph 		putleaf( PCC_ICON , width( ap ) , 0 , PCCT_INT , (char *) 0 );
128218467Sralph 		putop( PCC_CM , PCCT_INT );
128318467Sralph 		putop( PCC_CALL , PCCT_INT );
1284766Speter 		putdot( filename , line );
12859139Smckusick 		if (opt('t') && op == O_NEW) {
128618467Sralph 		    putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
12879139Smckusick 			    , "_blkclr" );
128815934Smckusick 		    (void) stkrval(alv, NLNIL , (long) RREQ );
128918467Sralph 		    putleaf( PCC_ICON , width( ap ) , 0 , PCCT_INT , (char *) 0 );
129018467Sralph 		    putop( PCC_CM , PCCT_INT );
129118467Sralph 		    putop( PCC_CALL , PCCT_INT );
12929139Smckusick 		    putdot( filename , line );
12939139Smckusick 		}
1294766Speter 		return;
1295766Speter 
1296766Speter 	case O_DATE:
1297766Speter 	case O_TIME:
1298766Speter 		if (argc != 1) {
1299766Speter 			error("%s expects one argument", p->symbol);
1300766Speter 			return;
1301766Speter 		}
130218467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1303766Speter 			, op == O_DATE ? "_DATE" : "_TIME" );
130415934Smckusick 		ap = stklval(argv->list_node.list, MOD|NOUSE);
1305766Speter 		if (ap == NIL)
1306766Speter 			return;
1307766Speter 		if (classify(ap) != TSTR || width(ap) != 10) {
1308766Speter 			error("Argument to %s must be a alfa, not %s", p->symbol, nameof(ap));
1309766Speter 			return;
1310766Speter 		}
131118467Sralph 		putop( PCC_CALL , PCCT_INT );
1312766Speter 		putdot( filename , line );
1313766Speter 		return;
1314766Speter 
1315766Speter 	case O_HALT:
1316766Speter 		if (argc != 0) {
1317766Speter 			error("halt takes no arguments");
1318766Speter 			return;
1319766Speter 		}
132018467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1321766Speter 			, "_HALT" );
1322766Speter 
132318467Sralph 		putop( PCCOM_UNARY PCC_CALL , PCCT_INT );
1324766Speter 		putdot( filename , line );
132515934Smckusick 		noreach = TRUE;
1326766Speter 		return;
1327766Speter 
1328766Speter 	case O_ARGV:
1329766Speter 		if (argc != 2) {
1330766Speter 			error("argv takes two arguments");
1331766Speter 			return;
1332766Speter 		}
133318467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1334766Speter 			, "_ARGV" );
133515934Smckusick 		ap = stkrval(argv->list_node.list, NLNIL , (long) RREQ );
133615934Smckusick 		if (ap == NLNIL)
1337766Speter 			return;
1338766Speter 		if (isnta(ap, "i")) {
1339766Speter 			error("argv's first argument must be an integer, not %s", nameof(ap));
1340766Speter 			return;
1341766Speter 		}
134215934Smckusick 		al = argv->list_node.next;
134315934Smckusick 		ap = stklval(al->list_node.list, MOD|NOUSE);
134415934Smckusick 		if (ap == NLNIL)
1345766Speter 			return;
1346766Speter 		if (classify(ap) != TSTR) {
1347766Speter 			error("argv's second argument must be a string, not %s", nameof(ap));
1348766Speter 			return;
1349766Speter 		}
135018467Sralph 		putop( PCC_CM , PCCT_INT );
135118467Sralph 		putleaf( PCC_ICON , width( ap ) , 0 , PCCT_INT , (char *) 0 );
135218467Sralph 		putop( PCC_CM , PCCT_INT );
135318467Sralph 		putop( PCC_CALL , PCCT_INT );
1354766Speter 		putdot( filename , line );
1355766Speter 		return;
1356766Speter 
1357766Speter 	case O_STLIM:
1358766Speter 		if (argc != 1) {
1359766Speter 			error("stlimit requires one argument");
1360766Speter 			return;
1361766Speter 		}
136218467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1363766Speter 			, "_STLIM" );
136415934Smckusick 		ap = stkrval(argv->list_node.list, NLNIL , (long) RREQ );
136515934Smckusick 		if (ap == NLNIL)
1366766Speter 			return;
1367766Speter 		if (isnta(ap, "i")) {
1368766Speter 			error("stlimit's argument must be an integer, not %s", nameof(ap));
1369766Speter 			return;
1370766Speter 		}
137118467Sralph 		putop( PCC_CALL , PCCT_INT );
1372766Speter 		putdot( filename , line );
1373766Speter 		return;
1374766Speter 
1375766Speter 	case O_REMOVE:
1376766Speter 		if (argc != 1) {
1377766Speter 			error("remove expects one argument");
1378766Speter 			return;
1379766Speter 		}
138018467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1381766Speter 			, "_REMOVE" );
138215934Smckusick 		ap = stkrval(argv->list_node.list, NLNIL, (long) RREQ );
138315934Smckusick 		if (ap == NLNIL)
1384766Speter 			return;
1385766Speter 		if (classify(ap) != TSTR) {
1386766Speter 			error("remove's argument must be a string, not %s", nameof(ap));
1387766Speter 			return;
1388766Speter 		}
138918467Sralph 		putleaf( PCC_ICON , width( ap ) , 0 , PCCT_INT , (char *) 0 );
139018467Sralph 		putop( PCC_CM , PCCT_INT );
139118467Sralph 		putop( PCC_CALL , PCCT_INT );
1392766Speter 		putdot( filename , line );
1393766Speter 		return;
1394766Speter 
1395766Speter 	case O_LLIMIT:
1396766Speter 		if (argc != 2) {
1397766Speter 			error("linelimit expects two arguments");
1398766Speter 			return;
1399766Speter 		}
140018467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1401766Speter 			, "_LLIMIT" );
140215934Smckusick 		ap = stklval(argv->list_node.list, NOFLAGS|NOUSE);
140315934Smckusick 		if (ap == NLNIL)
1404766Speter 			return;
1405766Speter 		if (!text(ap)) {
1406766Speter 			error("linelimit's first argument must be a text file, not %s", nameof(ap));
1407766Speter 			return;
1408766Speter 		}
140915934Smckusick 		al = argv->list_node.next;
141015934Smckusick 		ap = stkrval(al->list_node.list, NLNIL , (long) RREQ );
141115934Smckusick 		if (ap == NLNIL)
1412766Speter 			return;
1413766Speter 		if (isnta(ap, "i")) {
1414766Speter 			error("linelimit's second argument must be an integer, not %s", nameof(ap));
1415766Speter 			return;
1416766Speter 		}
141718467Sralph 		putop( PCC_CM , PCCT_INT );
141818467Sralph 		putop( PCC_CALL , PCCT_INT );
1419766Speter 		putdot( filename , line );
1420766Speter 		return;
1421766Speter 	case O_PAGE:
1422766Speter 		if (argc != 1) {
1423766Speter 			error("page expects one argument");
1424766Speter 			return;
1425766Speter 		}
142618467Sralph 		putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
142718467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1428766Speter 			, "_UNIT" );
142915934Smckusick 		ap = stklval(argv->list_node.list, NOFLAGS);
143015934Smckusick 		if (ap == NLNIL)
1431766Speter 			return;
1432766Speter 		if (!text(ap)) {
1433766Speter 			error("Argument to page must be a text file, not %s", nameof(ap));
1434766Speter 			return;
1435766Speter 		}
143618467Sralph 		putop( PCC_CALL , PCCT_INT );
143718467Sralph 		putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
1438766Speter 		putdot( filename , line );
1439766Speter 		if ( opt( 't' ) ) {
144018467Sralph 		    putleaf( PCC_ICON , 0 , 0
144118467Sralph 			, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1442766Speter 			, "_PAGE" );
144318467Sralph 		    putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
1444766Speter 		} else {
144518467Sralph 		    putleaf( PCC_ICON , 0 , 0
144618467Sralph 			, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1447766Speter 			, "_fputc" );
144818467Sralph 		    putleaf( PCC_ICON , '\f' , 0 , (int) PCCT_CHAR , (char *) 0 );
144918467Sralph 		    putleaf( PCC_ICON , 0 , 0
145018467Sralph 			, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1451766Speter 			, "_ACTFILE" );
145218467Sralph 		    putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
145318467Sralph 		    putop( PCC_CALL , PCCT_INT );
145418467Sralph 		    putop( PCC_CM , PCCT_INT );
1455766Speter 		}
145618467Sralph 		putop( PCC_CALL , PCCT_INT );
1457766Speter 		putdot( filename , line );
1458766Speter 		return;
1459766Speter 
14607928Smckusick 	case O_ASRT:
14617928Smckusick 		if (!opt('t'))
14627928Smckusick 			return;
14637928Smckusick 		if (argc == 0 || argc > 2) {
14647928Smckusick 			error("Assert expects one or two arguments");
14657928Smckusick 			return;
14667928Smckusick 		}
14679139Smckusick 		if (argc == 2)
14689139Smckusick 			cmd = "_ASRTS";
14699139Smckusick 		else
14709139Smckusick 			cmd = "_ASRT";
147118467Sralph 		putleaf( PCC_ICON , 0 , 0
147218467Sralph 		    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , cmd );
147315934Smckusick 		ap = stkrval(argv->list_node.list, NLNIL , (long) RREQ );
147415934Smckusick 		if (ap == NLNIL)
14757928Smckusick 			return;
14767928Smckusick 		if (isnta(ap, "b"))
14777928Smckusick 			error("Assert expression must be Boolean, not %ss", nameof(ap));
14787928Smckusick 		if (argc == 2) {
14797928Smckusick 			/*
14807928Smckusick 			 * Optional second argument is a string specifying
14817928Smckusick 			 * why the assertion failed.
14827928Smckusick 			 */
148315934Smckusick 			al = argv->list_node.next;
148415934Smckusick 			al = (struct tnode *) stkrval(al->list_node.list, NLNIL , (long) RREQ );
148515934Smckusick 			if (al == TR_NIL)
14867928Smckusick 				return;
148715934Smckusick 			if (classify((struct nl *) al) != TSTR) {
148815934Smckusick 				error("Second argument to assert must be a string, not %s", nameof((struct nl *) al));
14897928Smckusick 				return;
14907928Smckusick 			}
149118467Sralph 			putop( PCC_CM , PCCT_INT );
14927928Smckusick 		}
149318467Sralph 		putop( PCC_CALL , PCCT_INT );
14947928Smckusick 		putdot( filename , line );
14957928Smckusick 		return;
14967928Smckusick 
1497766Speter 	case O_PACK:
1498766Speter 		if (argc != 3) {
1499766Speter 			error("pack expects three arguments");
1500766Speter 			return;
1501766Speter 		}
150218467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1503766Speter 			, "_PACK" );
1504766Speter 		pu = "pack(a,i,z)";
150515934Smckusick 		pua = (al = argv)->list_node.list;
150615934Smckusick 		pui = (al = al->list_node.next)->list_node.list;
150715934Smckusick 		puz = (al = al->list_node.next)->list_node.list;
1508766Speter 		goto packunp;
1509766Speter 	case O_UNPACK:
1510766Speter 		if (argc != 3) {
1511766Speter 			error("unpack expects three arguments");
1512766Speter 			return;
1513766Speter 		}
151418467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1515766Speter 			, "_UNPACK" );
1516766Speter 		pu = "unpack(z,a,i)";
151715934Smckusick 		puz = (al = argv)->list_node.list;
151815934Smckusick 		pua = (al = al->list_node.next)->list_node.list;
151915934Smckusick 		pui = (al = al->list_node.next)->list_node.list;
1520766Speter packunp:
152115934Smckusick 		ap = stkrval(pui, NLNIL , (long) RREQ );
1522766Speter 		if (ap == NIL)
1523766Speter 			return;
1524766Speter 		ap = stklval(pua, op == O_PACK ? NOFLAGS : MOD|NOUSE);
1525766Speter 		if (ap == NIL)
1526766Speter 			return;
1527766Speter 		if (ap->class != ARRAY) {
1528766Speter 			error("%s requires a to be an unpacked array, not %s", pu, nameof(ap));
1529766Speter 			return;
1530766Speter 		}
153118467Sralph 		putop( PCC_CM , PCCT_INT );
153215934Smckusick 		al = (struct tnode *) stklval(puz, op == O_UNPACK ? NOFLAGS : MOD|NOUSE);
153315934Smckusick 		if (((struct nl *) al)->class != ARRAY) {
1534766Speter 			error("%s requires z to be a packed array, not %s", pu, nameof(ap));
1535766Speter 			return;
1536766Speter 		}
153715934Smckusick 		if (((struct nl *) al)->type == NIL ||
153815934Smckusick 			((struct nl *) ap)->type == NIL)
1539766Speter 			return;
154015934Smckusick 		if (((struct nl *) al)->type != ((struct nl *) ap)->type) {
1541766Speter 			error("%s requires a and z to be arrays of the same type", pu, nameof(ap));
1542766Speter 			return;
1543766Speter 		}
154418467Sralph 		putop( PCC_CM , PCCT_INT );
154515934Smckusick 		k = width((struct nl *) al);
1546766Speter 		itemwidth = width(ap->type);
1547766Speter 		ap = ap->chain;
154815934Smckusick 		al = ((struct tnode *) ((struct nl *) al)->chain);
154915934Smckusick 		if (ap->chain != NIL || ((struct nl *) al)->chain != NIL) {
1550766Speter 			error("%s requires a and z to be single dimension arrays", pu);
1551766Speter 			return;
1552766Speter 		}
1553766Speter 		if (ap == NIL || al == NIL)
1554766Speter 			return;
1555766Speter 		/*
1556766Speter 		 * al is the range for z i.e. u..v
1557766Speter 		 * ap is the range for a i.e. m..n
1558766Speter 		 * i will be n-m+1
1559766Speter 		 * j will be v-u+1
1560766Speter 		 */
1561766Speter 		i = ap->range[1] - ap->range[0] + 1;
156215934Smckusick 		j = ((struct nl *) al)->range[1] -
156315934Smckusick 			((struct nl *) al)->range[0] + 1;
1564766Speter 		if (i < j) {
156515934Smckusick 			error("%s cannot have more elements in a (%d) than in z (%d)", pu, (char *) j, (char *) i);
1566766Speter 			return;
1567766Speter 		}
1568766Speter 		/*
1569766Speter 		 * get n-m-(v-u) and m for the interpreter
1570766Speter 		 */
1571766Speter 		i -= j;
1572766Speter 		j = ap->range[0];
157318467Sralph 		putleaf( PCC_ICON , itemwidth , 0 , PCCT_INT , (char *) 0 );
157418467Sralph 		putop( PCC_CM , PCCT_INT );
157518467Sralph 		putleaf( PCC_ICON , j , 0 , PCCT_INT , (char *) 0 );
157618467Sralph 		putop( PCC_CM , PCCT_INT );
157718467Sralph 		putleaf( PCC_ICON , i , 0 , PCCT_INT , (char *) 0 );
157818467Sralph 		putop( PCC_CM , PCCT_INT );
157918467Sralph 		putleaf( PCC_ICON , k , 0 , PCCT_INT , (char *) 0 );
158018467Sralph 		putop( PCC_CM , PCCT_INT );
158118467Sralph 		putop( PCC_CALL , PCCT_INT );
1582766Speter 		putdot( filename , line );
1583766Speter 		return;
1584766Speter 	case 0:
15857928Smckusick 		error("%s is an unimplemented extension", p->symbol);
1586766Speter 		return;
1587766Speter 
1588766Speter 	default:
1589766Speter 		panic("proc case");
1590766Speter 	}
1591766Speter }
1592766Speter #endif PC
1593