xref: /csrg-svn/usr.bin/pascal/src/pcproc.c (revision 62213)
148116Sbostic /*-
2*62213Sbostic  * Copyright (c) 1980, 1993
3*62213Sbostic  *	The Regents of the University of California.  All rights reserved.
448116Sbostic  *
548116Sbostic  * %sccs.include.redist.c%
622216Sdist  */
7766Speter 
815934Smckusick #ifndef lint
9*62213Sbostic static char sccsid[] = "@(#)pcproc.c	8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
11766Speter 
12766Speter #include "whoami.h"
13766Speter #ifdef PC
14766Speter     /*
15766Speter      * and to the end of the file
16766Speter      */
17766Speter #include "0.h"
18766Speter #include "tree.h"
1910372Speter #include "objfmt.h"
20766Speter #include "opcode.h"
2110372Speter #include "pc.h"
2218467Sralph #include <pcc.h>
2311333Speter #include "tmps.h"
2415934Smckusick #include "tree_ty.h"
25766Speter 
26766Speter /*
2711883Smckusick  * The constant EXPOSIZE specifies the number of digits in the exponent
2811883Smckusick  * of real numbers.
2911883Smckusick  *
309229Smckusick  * The constant REALSPC defines the amount of forced padding preceeding
319229Smckusick  * real numbers when they are printed. If REALSPC == 0, then no padding
329229Smckusick  * is added, REALSPC == 1 adds one extra blank irregardless of the width
339229Smckusick  * specified by the user.
349229Smckusick  *
359229Smckusick  * N.B. - Values greater than one require program mods.
369229Smckusick  */
3711883Smckusick #define EXPOSIZE	2
3811883Smckusick #define	REALSPC		0
399229Smckusick 
409229Smckusick /*
41766Speter  * The following array is used to determine which classes may be read
42766Speter  * from textfiles. It is indexed by the return value from classify.
43766Speter  */
44766Speter #define rdops(x) rdxxxx[(x)-(TFIRST)]
45766Speter 
46766Speter int rdxxxx[] = {
47766Speter 	0,		/* -7 file types */
48766Speter 	0,		/* -6 record types */
49766Speter 	0,		/* -5 array types */
50766Speter 	O_READE,	/* -4 scalar types */
51766Speter 	0,		/* -3 pointer types */
52766Speter 	0,		/* -2 set types */
53766Speter 	0,		/* -1 string types */
54766Speter 	0,		/*  0 nil, no type */
55766Speter 	O_READE,	/*  1 boolean */
56766Speter 	O_READC,	/*  2 character */
57766Speter 	O_READ4,	/*  3 integer */
58766Speter 	O_READ8		/*  4 real */
59766Speter };
60766Speter 
61766Speter /*
62766Speter  * Proc handles procedure calls.
63766Speter  * Non-builtin procedures are "buck-passed" to func (with a flag
64766Speter  * indicating that they are actually procedures.
65766Speter  * builtin procedures are handled here.
66766Speter  */
67766Speter pcproc(r)
6815934Smckusick 	struct tnode *r;	/* T_PCALL */
69766Speter {
70766Speter 	register struct nl *p;
7115934Smckusick 	register struct tnode *alv, *al;
7215934Smckusick 	register op;
73766Speter 	struct nl *filetype, *ap;
7415934Smckusick 	int argc, typ, fmtspec, strfmt;
7515934Smckusick 	struct tnode *argv, *file;
767967Smckusick 	char fmt, format[20], *strptr, *cmd;
7715934Smckusick 	int prec, field, strnglen, fmtstart;
7815934Smckusick 	char *pu;
7915934Smckusick 	struct tnode *pua, *pui, *puz;
80766Speter 	int i, j, k;
81766Speter 	int itemwidth;
823833Speter 	char		*readname;
833833Speter 	struct nl	*tempnlp;
843833Speter 	long		readtype;
853833Speter 	struct tmps	soffset;
8615935Smckusick 	bool		soffset_flag;
87766Speter 
88766Speter #define	CONPREC 4
89766Speter #define	VARPREC 8
90766Speter #define	CONWIDTH 1
91766Speter #define	VARWIDTH 2
92766Speter #define SKIP 16
93766Speter 
94766Speter 	/*
95766Speter 	 * Verify that the name is
96766Speter 	 * defined and is that of a
97766Speter 	 * procedure.
98766Speter 	 */
9915934Smckusick 	p = lookup(r->pcall_node.proc_id);
10015934Smckusick 	if (p == NLNIL) {
10115934Smckusick 		rvlist(r->pcall_node.arg);
102766Speter 		return;
103766Speter 	}
1041197Speter 	if (p->class != PROC && p->class != FPROC) {
105766Speter 		error("Can't call %s, its %s not a procedure", p->symbol, classes[p->class]);
10615934Smckusick 		rvlist(r->pcall_node.arg);
107766Speter 		return;
108766Speter 	}
10915934Smckusick 	argv = r->pcall_node.arg;
110766Speter 
111766Speter 	/*
112766Speter 	 * Call handles user defined
113766Speter 	 * procedures and functions.
114766Speter 	 */
115766Speter 	if (bn != 0) {
11615934Smckusick 		(void) call(p, argv, PROC, bn);
117766Speter 		return;
118766Speter 	}
119766Speter 
120766Speter 	/*
121766Speter 	 * Call to built-in procedure.
122766Speter 	 * Count the arguments.
123766Speter 	 */
124766Speter 	argc = 0;
12515934Smckusick 	for (al = argv; al != TR_NIL; al = al->list_node.next)
126766Speter 		argc++;
127766Speter 
128766Speter 	/*
129766Speter 	 * Switch on the operator
130766Speter 	 * associated with the built-in
131766Speter 	 * procedure in the namelist
132766Speter 	 */
133766Speter 	op = p->value[0] &~ NSTAND;
134766Speter 	if (opt('s') && (p->value[0] & NSTAND)) {
135766Speter 		standard();
136766Speter 		error("%s is a nonstandard procedure", p->symbol);
137766Speter 	}
138766Speter 	switch (op) {
139766Speter 
140766Speter 	case O_ABORT:
141766Speter 		if (argc != 0)
142766Speter 			error("null takes no arguments");
143766Speter 		return;
144766Speter 
145766Speter 	case O_FLUSH:
146766Speter 		if (argc == 0) {
14718467Sralph 			putleaf( PCC_ICON , 0 , 0 , PCCT_INT , "_PFLUSH" );
14818467Sralph 			putop( PCCOM_UNARY PCC_CALL , PCCT_INT );
149766Speter 			putdot( filename , line );
150766Speter 			return;
151766Speter 		}
152766Speter 		if (argc != 1) {
153766Speter 			error("flush takes at most one argument");
154766Speter 			return;
155766Speter 		}
15618467Sralph 		putleaf( PCC_ICON , 0 , 0
15718467Sralph 			, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
158766Speter 			, "_FLUSH" );
15915934Smckusick 		ap = stklval(argv->list_node.list, NOFLAGS);
16015934Smckusick 		if (ap == NLNIL)
161766Speter 			return;
162766Speter 		if (ap->class != FILET) {
163766Speter 			error("flush's argument must be a file, not %s", nameof(ap));
164766Speter 			return;
165766Speter 		}
16618467Sralph 		putop( PCC_CALL , PCCT_INT );
167766Speter 		putdot( filename , line );
168766Speter 		return;
169766Speter 
170766Speter 	case O_MESSAGE:
171766Speter 	case O_WRITEF:
172766Speter 	case O_WRITLN:
173766Speter 		/*
174766Speter 		 * Set up default file "output"'s type
175766Speter 		 */
176766Speter 		file = NIL;
177766Speter 		filetype = nl+T1CHAR;
178766Speter 		/*
179766Speter 		 * Determine the file implied
180766Speter 		 * for the write and generate
181766Speter 		 * code to make it the active file.
182766Speter 		 */
183766Speter 		if (op == O_MESSAGE) {
184766Speter 			/*
185766Speter 			 * For message, all that matters
186766Speter 			 * is that the filetype is
187766Speter 			 * a character file.
188766Speter 			 * Thus "output" will suit us fine.
189766Speter 			 */
19018467Sralph 			putleaf( PCC_ICON , 0 , 0 , PCCT_INT , "_PFLUSH" );
19118467Sralph 			putop( PCCOM_UNARY PCC_CALL , PCCT_INT );
192766Speter 			putdot( filename , line );
19315934Smckusick 			putRV( (char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
19418467Sralph 				PCCTM_PTR|PCCT_STRTY );
19518467Sralph 			putLV( "__err" , 0 , 0 , NGLOBAL , PCCTM_PTR|PCCT_STRTY );
19618467Sralph 			putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
197766Speter 			putdot( filename , line );
19815934Smckusick 		} else if (argv != TR_NIL && (al = argv->list_node.list)->tag !=
19915934Smckusick 					T_WEXP) {
200766Speter 			/*
201766Speter 			 * If there is a first argument which has
202766Speter 			 * no write widths, then it is potentially
203766Speter 			 * a file name.
204766Speter 			 */
205766Speter 			codeoff();
20615934Smckusick 			ap = stkrval(argv->list_node.list, NLNIL, (long) RREQ );
207766Speter 			codeon();
20815934Smckusick 			if (ap == NLNIL)
20915934Smckusick 				argv = argv->list_node.next;
210766Speter 			if (ap != NIL && ap->class == FILET) {
211766Speter 				/*
212766Speter 				 * Got "write(f, ...", make
213766Speter 				 * f the active file, and save
214766Speter 				 * it and its type for use in
215766Speter 				 * processing the rest of the
216766Speter 				 * arguments to write.
217766Speter 				 */
21815934Smckusick 				putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
21918467Sralph 					PCCTM_PTR|PCCT_STRTY );
22018467Sralph 				putleaf( PCC_ICON , 0 , 0
22118467Sralph 				    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
222766Speter 				    , "_UNIT" );
22315934Smckusick 				file = argv->list_node.list;
224766Speter 				filetype = ap->type;
22515934Smckusick 				(void) stklval(argv->list_node.list, NOFLAGS);
22618467Sralph 				putop( PCC_CALL , PCCT_INT );
22718467Sralph 				putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
228766Speter 				putdot( filename , line );
229766Speter 				/*
230766Speter 				 * Skip over the first argument
231766Speter 				 */
23215934Smckusick 				argv = argv->list_node.next;
233766Speter 				argc--;
234766Speter 			} else {
235766Speter 				/*
236766Speter 				 * Set up for writing on
237766Speter 				 * standard output.
238766Speter 				 */
23915934Smckusick 				putRV((char *) 0, cbn , CURFILEOFFSET ,
24018467Sralph 					NLOCAL , PCCTM_PTR|PCCT_STRTY );
2413833Speter 				putLV( "_output" , 0 , 0 , NGLOBAL ,
24218467Sralph 					PCCTM_PTR|PCCT_STRTY );
24318467Sralph 				putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
244766Speter 				putdot( filename , line );
2457954Speter 				output->nl_flags |= NUSED;
246766Speter 			}
247766Speter 		} else {
24815934Smckusick 			putRV((char *) 0, cbn , CURFILEOFFSET , NLOCAL ,
24918467Sralph 				PCCTM_PTR|PCCT_STRTY );
25018467Sralph 			putLV( "_output" , 0 , 0 , NGLOBAL , PCCTM_PTR|PCCT_STRTY );
25118467Sralph 			putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
252766Speter 			putdot( filename , line );
2537954Speter 			output->nl_flags |= NUSED;
254766Speter 		}
255766Speter 		/*
256766Speter 		 * Loop and process each
257766Speter 		 * of the arguments.
258766Speter 		 */
25915934Smckusick 		for (; argv != TR_NIL; argv = argv->list_node.next) {
26015935Smckusick 		        soffset_flag = FALSE;
261766Speter 			/*
262766Speter 			 * fmtspec indicates the type (CONstant or VARiable)
263766Speter 			 *	and number (none, WIDTH, and/or PRECision)
264766Speter 			 *	of the fields in the printf format for this
265766Speter 			 *	output variable.
266766Speter 			 * fmt is the format output indicator (D, E, F, O, X, S)
267766Speter 			 * fmtstart = 0 for leading blank; = 1 for no blank
268766Speter 			 */
269766Speter 			fmtspec = NIL;
270766Speter 			fmt = 'D';
271766Speter 			fmtstart = 1;
27215934Smckusick 			al = argv->list_node.list;
273766Speter 			if (al == NIL)
274766Speter 				continue;
27515934Smckusick 			if (al->tag == T_WEXP)
27615934Smckusick 				alv = al->wexpr_node.expr1;
277766Speter 			else
278766Speter 				alv = al;
27915934Smckusick 			if (alv == TR_NIL)
280766Speter 				continue;
281766Speter 			codeoff();
28215934Smckusick 			ap = stkrval(alv, NLNIL , (long) RREQ );
283766Speter 			codeon();
28415934Smckusick 			if (ap == NLNIL)
285766Speter 				continue;
286766Speter 			typ = classify(ap);
28715934Smckusick 			if (al->tag == T_WEXP) {
288766Speter 				/*
289766Speter 				 * Handle width expressions.
290766Speter 				 * The basic game here is that width
291766Speter 				 * expressions get evaluated. If they
292766Speter 				 * are constant, the value is placed
293766Speter 				 * directly in the format string.
294766Speter 				 * Otherwise the value is pushed onto
295766Speter 				 * the stack and an indirection is
296766Speter 				 * put into the format string.
297766Speter 				 */
29815934Smckusick 				if (al->wexpr_node.expr3 ==
29915934Smckusick 						(struct tnode *) OCT)
300766Speter 					fmt = 'O';
30115934Smckusick 				else if (al->wexpr_node.expr3 ==
30215934Smckusick 						(struct tnode *) HEX)
303766Speter 					fmt = 'X';
30415934Smckusick 				else if (al->wexpr_node.expr3 != TR_NIL) {
305766Speter 					/*
306766Speter 					 * Evaluate second format spec
307766Speter 					 */
30815934Smckusick 					if ( constval(al->wexpr_node.expr3)
309766Speter 					    && isa( con.ctype , "i" ) ) {
310766Speter 						fmtspec += CONPREC;
311766Speter 						prec = con.crval;
312766Speter 					} else {
313766Speter 						fmtspec += VARPREC;
314766Speter 					}
315766Speter 					fmt = 'f';
316766Speter 					switch ( typ ) {
317766Speter 					case TINT:
318766Speter 						if ( opt( 's' ) ) {
319766Speter 						    standard();
320766Speter 						    error("Writing %ss with two write widths is non-standard", clnames[typ]);
321766Speter 						}
322766Speter 						/* and fall through */
323766Speter 					case TDOUBLE:
324766Speter 						break;
325766Speter 					default:
326766Speter 						error("Cannot write %ss with two write widths", clnames[typ]);
327766Speter 						continue;
328766Speter 					}
329766Speter 				}
330766Speter 				/*
331766Speter 				 * Evaluate first format spec
332766Speter 				 */
33315934Smckusick 				if (al->wexpr_node.expr2 != TR_NIL) {
33415934Smckusick 					if ( constval(al->wexpr_node.expr2)
335766Speter 					    && isa( con.ctype , "i" ) ) {
336766Speter 						fmtspec += CONWIDTH;
337766Speter 						field = con.crval;
338766Speter 					} else {
339766Speter 						fmtspec += VARWIDTH;
340766Speter 					}
341766Speter 				}
342766Speter 				if ((fmtspec & CONPREC) && prec < 0 ||
343766Speter 				    (fmtspec & CONWIDTH) && field < 0) {
344766Speter 					error("Negative widths are not allowed");
345766Speter 					continue;
346766Speter 				}
3473180Smckusic 				if ( opt('s') &&
3483180Smckusic 				    ((fmtspec & CONPREC) && prec == 0 ||
3493180Smckusic 				    (fmtspec & CONWIDTH) && field == 0)) {
3503180Smckusic 					standard();
3513180Smckusic 					error("Zero widths are non-standard");
3523180Smckusic 				}
353766Speter 			}
354766Speter 			if (filetype != nl+T1CHAR) {
355766Speter 				if (fmt == 'O' || fmt == 'X') {
356766Speter 					error("Oct/hex allowed only on text files");
357766Speter 					continue;
358766Speter 				}
359766Speter 				if (fmtspec) {
360766Speter 					error("Write widths allowed only on text files");
361766Speter 					continue;
362766Speter 				}
363766Speter 				/*
364766Speter 				 * Generalized write, i.e.
365766Speter 				 * to a non-textfile.
366766Speter 				 */
36718467Sralph 				putleaf( PCC_ICON , 0 , 0
36818467Sralph 				    , (int) (PCCM_ADDTYPE(
36918467Sralph 					PCCM_ADDTYPE(
37018467Sralph 					    PCCM_ADDTYPE( p2type( filetype )
37118467Sralph 						    , PCCTM_PTR )
37218467Sralph 					    , PCCTM_FTN )
37318467Sralph 					, PCCTM_PTR ))
374766Speter 				    , "_FNIL" );
37515934Smckusick 				(void) stklval(file, NOFLAGS);
37618467Sralph 				putop( PCC_CALL
37718467Sralph 				    , PCCM_ADDTYPE( p2type( filetype ) , PCCTM_PTR ) );
37818467Sralph 				putop( PCCOM_UNARY PCC_MUL , p2type( filetype ) );
379766Speter 				/*
380766Speter 				 * file^ := ...
381766Speter 				 */
382766Speter 				switch ( classify( filetype ) ) {
383766Speter 				    case TBOOL:
384766Speter 				    case TCHAR:
385766Speter 				    case TINT:
386766Speter 				    case TSCAL:
3874589Speter 					precheck( filetype , "_RANG4"  , "_RSNG4" );
388766Speter 					    /* and fall through */
389766Speter 				    case TDOUBLE:
390766Speter 				    case TPTR:
39115934Smckusick 					ap = rvalue( argv->list_node.list , filetype , RREQ );
392766Speter 					break;
393766Speter 				    default:
39415934Smckusick 					ap = rvalue( argv->list_node.list , filetype , LREQ );
395766Speter 					break;
396766Speter 				}
397766Speter 				if (ap == NIL)
398766Speter 					continue;
39915934Smckusick 				if (incompat(ap, filetype, argv->list_node.list)) {
400766Speter 					cerror("Type mismatch in write to non-text file");
401766Speter 					continue;
402766Speter 				}
403766Speter 				switch ( classify( filetype ) ) {
404766Speter 				    case TBOOL:
405766Speter 				    case TCHAR:
406766Speter 				    case TINT:
407766Speter 				    case TSCAL:
40810373Speter 					    postcheck(filetype, ap);
40910373Speter 					    sconv(p2type(ap), p2type(filetype));
410766Speter 						/* and fall through */
411766Speter 				    case TDOUBLE:
412766Speter 				    case TPTR:
41318467Sralph 					    putop( PCC_ASSIGN , p2type( filetype ) );
414766Speter 					    putdot( filename , line );
415766Speter 					    break;
416766Speter 				    default:
41718467Sralph 					    putstrop(PCC_STASG,
41818467Sralph 						    PCCM_ADDTYPE(p2type(filetype),
41918467Sralph 							    PCCTM_PTR),
42015934Smckusick 						    (int) lwidth(filetype),
42111856Speter 						    align(filetype));
422766Speter 					    putdot( filename , line );
423766Speter 					    break;
424766Speter 				}
425766Speter 				/*
426766Speter 				 * put(file)
427766Speter 				 */
42818467Sralph 				putleaf( PCC_ICON , 0 , 0
42918467Sralph 				    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
430766Speter 				    , "_PUT" );
43115934Smckusick 				putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
43218467Sralph 					PCCTM_PTR|PCCT_STRTY );
43318467Sralph 				putop( PCC_CALL , PCCT_INT );
434766Speter 				putdot( filename , line );
435766Speter 				continue;
436766Speter 			}
437766Speter 			/*
438766Speter 			 * Write to a textfile
439766Speter 			 *
440766Speter 			 * Evaluate the expression
441766Speter 			 * to be written.
442766Speter 			 */
443766Speter 			if (fmt == 'O' || fmt == 'X') {
444766Speter 				if (opt('s')) {
445766Speter 					standard();
446766Speter 					error("Oct and hex are non-standard");
447766Speter 				}
448766Speter 				if (typ == TSTR || typ == TDOUBLE) {
449766Speter 					error("Can't write %ss with oct/hex", clnames[typ]);
450766Speter 					continue;
451766Speter 				}
452766Speter 				if (typ == TCHAR || typ == TBOOL)
453766Speter 					typ = TINT;
454766Speter 			}
455766Speter 			/*
456766Speter 			 * If there is no format specified by the programmer,
457766Speter 			 * implement the default.
458766Speter 			 */
459766Speter 			switch (typ) {
4606540Smckusick 			case TPTR:
4616540Smckusick 				warning();
4626540Smckusick 				if (opt('s')) {
4636540Smckusick 					standard();
4646540Smckusick 				}
4656540Smckusick 				error("Writing %ss to text files is non-standard",
4666540Smckusick 				    clnames[typ]);
4676540Smckusick 				/* and fall through */
468766Speter 			case TINT:
469766Speter 				if (fmt == 'f') {
470766Speter 					typ = TDOUBLE;
471766Speter 					goto tdouble;
472766Speter 				}
473766Speter 				if (fmtspec == NIL) {
474766Speter 					if (fmt == 'D')
475766Speter 						field = 10;
476766Speter 					else if (fmt == 'X')
477766Speter 						field = 8;
478766Speter 					else if (fmt == 'O')
479766Speter 						field = 11;
480766Speter 					else
481766Speter 						panic("fmt1");
482766Speter 					fmtspec = CONWIDTH;
483766Speter 				}
484766Speter 				break;
485766Speter 			case TCHAR:
486766Speter 			     tchar:
487766Speter 				fmt = 'c';
488766Speter 				break;
489766Speter 			case TSCAL:
4901629Speter 				warning();
491766Speter 				if (opt('s')) {
492766Speter 					standard();
493766Speter 				}
4946540Smckusick 				error("Writing %ss to text files is non-standard",
4956540Smckusick 				    clnames[typ]);
496766Speter 			case TBOOL:
497766Speter 				fmt = 's';
498766Speter 				break;
499766Speter 			case TDOUBLE:
500766Speter 			     tdouble:
501766Speter 				switch (fmtspec) {
502766Speter 				case NIL:
50311883Smckusick 					field = 14 + (5 + EXPOSIZE);
50411883Smckusick 				        prec = field - (5 + EXPOSIZE);
5053225Smckusic 					fmt = 'e';
506766Speter 					fmtspec = CONWIDTH + CONPREC;
507766Speter 					break;
508766Speter 				case CONWIDTH:
5099229Smckusick 					field -= REALSPC;
5109229Smckusick 					if (field < 1)
511766Speter 						field = 1;
51211883Smckusick 				        prec = field - (5 + EXPOSIZE);
513766Speter 					if (prec < 1)
514766Speter 						prec = 1;
515766Speter 					fmtspec += CONPREC;
5163225Smckusic 					fmt = 'e';
517766Speter 					break;
518766Speter 				case VARWIDTH:
519766Speter 					fmtspec += VARPREC;
5203225Smckusic 					fmt = 'e';
521766Speter 					break;
522766Speter 				case CONWIDTH + CONPREC:
523766Speter 				case CONWIDTH + VARPREC:
5249229Smckusick 					field -= REALSPC;
5259229Smckusick 					if (field < 1)
526766Speter 						field = 1;
527766Speter 				}
528766Speter 				format[0] = ' ';
5299229Smckusick 				fmtstart = 1 - REALSPC;
530766Speter 				break;
531766Speter 			case TSTR:
53215934Smckusick 				(void) constval( alv );
533766Speter 				switch ( classify( con.ctype ) ) {
534766Speter 				    case TCHAR:
535766Speter 					typ = TCHAR;
536766Speter 					goto tchar;
537766Speter 				    case TSTR:
538766Speter 					strptr = con.cpval;
539766Speter 					for (strnglen = 0;  *strptr++;  strnglen++) /* void */;
540766Speter 					strptr = con.cpval;
541766Speter 					break;
542766Speter 				    default:
543766Speter 					strnglen = width(ap);
544766Speter 					break;
545766Speter 				}
546766Speter 				fmt = 's';
547766Speter 				strfmt = fmtspec;
548766Speter 				if (fmtspec == NIL) {
549766Speter 					fmtspec = SKIP;
550766Speter 					break;
551766Speter 				}
552766Speter 				if (fmtspec & CONWIDTH) {
553766Speter 					if (field <= strnglen)
554766Speter 						fmtspec = SKIP;
555766Speter 					else
556766Speter 						field -= strnglen;
557766Speter 				}
558766Speter 				break;
559766Speter 			default:
560766Speter 				error("Can't write %ss to a text file", clnames[typ]);
561766Speter 				continue;
562766Speter 			}
563766Speter 			/*
564766Speter 			 * Generate the format string
565766Speter 			 */
566766Speter 			switch (fmtspec) {
567766Speter 			default:
568766Speter 				panic("fmt2");
569766Speter 			case NIL:
570766Speter 				if (fmt == 'c') {
571766Speter 					if ( opt( 't' ) ) {
57218467Sralph 					    putleaf( PCC_ICON , 0 , 0
57318467Sralph 						, PCCM_ADDTYPE( PCCTM_FTN|PCCT_INT , PCCTM_PTR )
574766Speter 						, "_WRITEC" );
57515934Smckusick 					    putRV((char *) 0 , cbn , CURFILEOFFSET ,
57618467Sralph 						    NLOCAL , PCCTM_PTR|PCCT_STRTY );
57715934Smckusick 					    (void) stkrval( alv , NLNIL , (long) RREQ );
57818467Sralph 					    putop( PCC_CM , PCCT_INT );
579766Speter 					} else {
58018467Sralph 					    putleaf( PCC_ICON , 0 , 0
58118467Sralph 						, PCCM_ADDTYPE( PCCTM_FTN|PCCT_INT , PCCTM_PTR )
582766Speter 						, "_fputc" );
58315934Smckusick 					    (void) stkrval( alv , NLNIL ,
58415934Smckusick 							(long) RREQ );
585766Speter 					}
58618467Sralph 					putleaf( PCC_ICON , 0 , 0
58718467Sralph 					    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
588766Speter 					    , "_ACTFILE" );
58915934Smckusick 					putRV((char *) 0, cbn , CURFILEOFFSET ,
59018467Sralph 						NLOCAL , PCCTM_PTR|PCCT_STRTY );
59118467Sralph 					putop( PCC_CALL , PCCT_INT );
59218467Sralph 					putop( PCC_CM , PCCT_INT );
59318467Sralph 					putop( PCC_CALL , PCCT_INT );
594766Speter 					putdot( filename , line );
595766Speter 				} else  {
596766Speter 					sprintf(&format[1], "%%%c", fmt);
597766Speter 					goto fmtgen;
598766Speter 				}
599766Speter 			case SKIP:
600766Speter 				break;
601766Speter 			case CONWIDTH:
602766Speter 				sprintf(&format[1], "%%%1D%c", field, fmt);
603766Speter 				goto fmtgen;
604766Speter 			case VARWIDTH:
605766Speter 				sprintf(&format[1], "%%*%c", fmt);
606766Speter 				goto fmtgen;
607766Speter 			case CONWIDTH + CONPREC:
608766Speter 				sprintf(&format[1], "%%%1D.%1D%c", field, prec, fmt);
609766Speter 				goto fmtgen;
610766Speter 			case CONWIDTH + VARPREC:
611766Speter 				sprintf(&format[1], "%%%1D.*%c", field, fmt);
612766Speter 				goto fmtgen;
613766Speter 			case VARWIDTH + CONPREC:
614766Speter 				sprintf(&format[1], "%%*.%1D%c", prec, fmt);
615766Speter 				goto fmtgen;
616766Speter 			case VARWIDTH + VARPREC:
617766Speter 				sprintf(&format[1], "%%*.*%c", fmt);
618766Speter 			fmtgen:
619766Speter 				if ( opt( 't' ) ) {
62018467Sralph 				    putleaf( PCC_ICON , 0 , 0
62118467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
622766Speter 					, "_WRITEF" );
62315934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
62418467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
62518467Sralph 				    putleaf( PCC_ICON , 0 , 0
62618467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
627766Speter 					, "_ACTFILE" );
62815934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
62918467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
63018467Sralph 				    putop( PCC_CALL , PCCT_INT );
63118467Sralph 				    putop( PCC_CM , PCCT_INT );
632766Speter 				} else {
63318467Sralph 				    putleaf( PCC_ICON , 0 , 0
63418467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
635766Speter 					, "_fprintf" );
63618467Sralph 				    putleaf( PCC_ICON , 0 , 0
63718467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
638766Speter 					, "_ACTFILE" );
63915934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
64018467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
64118467Sralph 				    putop( PCC_CALL , PCCT_INT );
642766Speter 				}
643766Speter 				putCONG( &format[ fmtstart ]
644766Speter 					, strlen( &format[ fmtstart ] )
645766Speter 					, LREQ );
64618467Sralph 				putop( PCC_CM , PCCT_INT );
647766Speter 				if ( fmtspec & VARWIDTH ) {
648766Speter 					/*
649766Speter 					 * either
650766Speter 					 *	,(temp=width,MAX(temp,...)),
651766Speter 					 * or
652766Speter 					 *	, MAX( width , ... ) ,
653766Speter 					 */
65415934Smckusick 				    if ( ( typ == TDOUBLE &&
65515934Smckusick 						al->wexpr_node.expr3 == TR_NIL )
656766Speter 					|| typ == TSTR ) {
65715935Smckusick 					soffset_flag = TRUE;
6583225Smckusic 					soffset = sizes[cbn].curtmps;
65915934Smckusick 					tempnlp = tmpalloc((long) (sizeof(long)),
6603225Smckusic 						nl+T4INT, REGOK);
66115934Smckusick 					putRV((char *) 0 , cbn ,
6623833Speter 					    tempnlp -> value[ NL_OFFS ] ,
66318467Sralph 					    tempnlp -> extra_flags , PCCT_INT );
66415934Smckusick 					ap = stkrval( al->wexpr_node.expr2 ,
66515934Smckusick 						NLNIL , (long) RREQ );
66618467Sralph 					putop( PCC_ASSIGN , PCCT_INT );
66718467Sralph 					putleaf( PCC_ICON , 0 , 0
66818467Sralph 					    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
669766Speter 					    , "_MAX" );
67015934Smckusick 					putRV((char *) 0 , cbn ,
6713833Speter 					    tempnlp -> value[ NL_OFFS ] ,
67218467Sralph 					    tempnlp -> extra_flags , PCCT_INT );
673766Speter 				    } else {
674766Speter 					if (opt('t')
675766Speter 					    || typ == TSTR || typ == TDOUBLE) {
67618467Sralph 					    putleaf( PCC_ICON , 0 , 0
67718467Sralph 						,PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT, PCCTM_PTR )
678766Speter 						,"_MAX" );
679766Speter 					}
68015934Smckusick 					ap = stkrval( al->wexpr_node.expr2,
68115934Smckusick 						NLNIL , (long) RREQ );
682766Speter 				    }
68315934Smckusick 				    if (ap == NLNIL)
684766Speter 					    continue;
685766Speter 				    if (isnta(ap,"i")) {
686766Speter 					    error("First write width must be integer, not %s", nameof(ap));
687766Speter 					    continue;
688766Speter 				    }
689766Speter 				    switch ( typ ) {
690766Speter 				    case TDOUBLE:
69118467Sralph 					putleaf( PCC_ICON , REALSPC , 0 , PCCT_INT , (char *) 0 );
69218467Sralph 					putop( PCC_CM , PCCT_INT );
69318467Sralph 					putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 );
69418467Sralph 					putop( PCC_CM , PCCT_INT );
69518467Sralph 					putop( PCC_CALL , PCCT_INT );
69615934Smckusick 					if ( al->wexpr_node.expr3 == TR_NIL ) {
697766Speter 						/*
698766Speter 						 * finish up the comma op
699766Speter 						 */
70018467Sralph 					    putop( PCC_COMOP , PCCT_INT );
701766Speter 					    fmtspec &= ~VARPREC;
70218467Sralph 					    putop( PCC_CM , PCCT_INT );
70318467Sralph 					    putleaf( PCC_ICON , 0 , 0
70418467Sralph 						, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
705766Speter 						, "_MAX" );
70615934Smckusick 					    putRV((char *) 0 , cbn ,
7073833Speter 						tempnlp -> value[ NL_OFFS ] ,
7083833Speter 						tempnlp -> extra_flags ,
70918467Sralph 						PCCT_INT );
71018467Sralph 					    putleaf( PCC_ICON ,
71111883Smckusick 						5 + EXPOSIZE + REALSPC ,
71218467Sralph 						0 , PCCT_INT , (char *) 0 );
71318467Sralph 					    putop( PCC_CM , PCCT_INT );
71418467Sralph 					    putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 );
71518467Sralph 					    putop( PCC_CM , PCCT_INT );
71618467Sralph 					    putop( PCC_CALL , PCCT_INT );
717766Speter 					}
71818467Sralph 					putop( PCC_CM , PCCT_INT );
719766Speter 					break;
720766Speter 				    case TSTR:
72118467Sralph 					putleaf( PCC_ICON , strnglen , 0 , PCCT_INT , (char *) 0 );
72218467Sralph 					putop( PCC_CM , PCCT_INT );
72318467Sralph 					putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
72418467Sralph 					putop( PCC_CM , PCCT_INT );
72518467Sralph 					putop( PCC_CALL , PCCT_INT );
72618467Sralph 					putop( PCC_COMOP , PCCT_INT );
72718467Sralph 					putop( PCC_CM , PCCT_INT );
728766Speter 					break;
729766Speter 				    default:
730766Speter 					if (opt('t')) {
73118467Sralph 					    putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
73218467Sralph 					    putop( PCC_CM , PCCT_INT );
73318467Sralph 					    putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
73418467Sralph 					    putop( PCC_CM , PCCT_INT );
73518467Sralph 					    putop( PCC_CALL , PCCT_INT );
736766Speter 					}
73718467Sralph 					putop( PCC_CM , PCCT_INT );
738766Speter 					break;
739766Speter 				    }
740766Speter 				}
741766Speter 				/*
742766Speter 				 * If there is a variable precision,
743766Speter 				 * evaluate it
744766Speter 				 */
745766Speter 				if (fmtspec & VARPREC) {
746766Speter 					if (opt('t')) {
74718467Sralph 					putleaf( PCC_ICON , 0 , 0
74818467Sralph 					    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
749766Speter 					    , "_MAX" );
750766Speter 					}
75115934Smckusick 					ap = stkrval( al->wexpr_node.expr3 ,
75215934Smckusick 						NLNIL , (long) RREQ );
753766Speter 					if (ap == NIL)
754766Speter 						continue;
755766Speter 					if (isnta(ap,"i")) {
756766Speter 						error("Second write width must be integer, not %s", nameof(ap));
757766Speter 						continue;
758766Speter 					}
759766Speter 					if (opt('t')) {
76018467Sralph 					    putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
76118467Sralph 					    putop( PCC_CM , PCCT_INT );
76218467Sralph 					    putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
76318467Sralph 					    putop( PCC_CM , PCCT_INT );
76418467Sralph 					    putop( PCC_CALL , PCCT_INT );
765766Speter 					}
76618467Sralph 				 	putop( PCC_CM , PCCT_INT );
767766Speter 				}
768766Speter 				/*
769766Speter 				 * evaluate the thing we want printed.
770766Speter 				 */
771766Speter 				switch ( typ ) {
7726540Smckusick 				case TPTR:
773766Speter 				case TCHAR:
774766Speter 				case TINT:
77515934Smckusick 				    (void) stkrval( alv , NLNIL , (long) RREQ );
77618467Sralph 				    putop( PCC_CM , PCCT_INT );
777766Speter 				    break;
778766Speter 				case TDOUBLE:
77915934Smckusick 				    ap = stkrval( alv , NLNIL , (long) RREQ );
78010373Speter 				    if (isnta(ap, "d")) {
78118467Sralph 					sconv(p2type(ap), PCCT_DOUBLE);
782766Speter 				    }
78318467Sralph 				    putop( PCC_CM , PCCT_INT );
784766Speter 				    break;
785766Speter 				case TSCAL:
786766Speter 				case TBOOL:
78718467Sralph 				    putleaf( PCC_ICON , 0 , 0
78818467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
789766Speter 					, "_NAM" );
79015934Smckusick 				    ap = stkrval( alv , NLNIL , (long) RREQ );
791766Speter 				    sprintf( format , PREFIXFORMAT , LABELPREFIX
792766Speter 					    , listnames( ap ) );
79318467Sralph 				    putleaf( PCC_ICON , 0 , 0 ,
79418467Sralph 					(int) (PCCTM_PTR | PCCT_CHAR), format );
79518467Sralph 				    putop( PCC_CM , PCCT_INT );
79618467Sralph 				    putop( PCC_CALL , PCCT_INT );
79718467Sralph 				    putop( PCC_CM , PCCT_INT );
798766Speter 				    break;
799766Speter 				case TSTR:
800766Speter 				    putCONG( "" , 0 , LREQ );
80118467Sralph 				    putop( PCC_CM , PCCT_INT );
802766Speter 				    break;
8036540Smckusick 				default:
8046540Smckusick 				    panic("fmt3");
8056540Smckusick 				    break;
806766Speter 				}
80718467Sralph 				putop( PCC_CALL , PCCT_INT );
808766Speter 				putdot( filename , line );
809766Speter 			}
810766Speter 			/*
811766Speter 			 * Write the string after its blank padding
812766Speter 			 */
813766Speter 			if (typ == TSTR ) {
814766Speter 				if ( opt( 't' ) ) {
81518467Sralph 				    putleaf( PCC_ICON , 0 , 0
81618467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
817766Speter 					, "_WRITES" );
81815934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
81918467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
82015934Smckusick 				    ap = stkrval(alv, NLNIL , (long) RREQ );
82118467Sralph 				    putop( PCC_CM , PCCT_INT );
822766Speter 				} else {
82318467Sralph 				    putleaf( PCC_ICON , 0 , 0
82418467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
825766Speter 					, "_fwrite" );
82615934Smckusick 				    ap = stkrval(alv, NLNIL , (long) RREQ );
827766Speter 				}
828766Speter 				if (strfmt & VARWIDTH) {
829766Speter 					    /*
830766Speter 					     *	min, inline expanded as
831766Speter 					     *	temp < len ? temp : len
832766Speter 					     */
83315934Smckusick 					putRV((char *) 0 , cbn ,
8343833Speter 					    tempnlp -> value[ NL_OFFS ] ,
83518467Sralph 					    tempnlp -> extra_flags , PCCT_INT );
83618467Sralph 					putleaf( PCC_ICON , strnglen , 0 , PCCT_INT , (char *) 0 );
83718467Sralph 					putop( PCC_LT , PCCT_INT );
83815934Smckusick 					putRV((char *) 0 , cbn ,
8393833Speter 					    tempnlp -> value[ NL_OFFS ] ,
84018467Sralph 					    tempnlp -> extra_flags , PCCT_INT );
84118467Sralph 					putleaf( PCC_ICON , strnglen , 0 , PCCT_INT , (char *) 0 );
84218467Sralph 					putop( PCC_COLON , PCCT_INT );
84318467Sralph 					putop( PCC_QUEST , PCCT_INT );
844766Speter 				} else {
845766Speter 					if (   ( fmtspec & SKIP )
846766Speter 					    && ( strfmt & CONWIDTH ) ) {
847766Speter 						strnglen = field;
848766Speter 					}
84918467Sralph 					putleaf( PCC_ICON , strnglen , 0 , PCCT_INT , (char *) 0 );
850766Speter 				}
85118467Sralph 				putop( PCC_CM , PCCT_INT );
85218467Sralph 				putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 );
85318467Sralph 				putop( PCC_CM , PCCT_INT );
85418467Sralph 				putleaf( PCC_ICON , 0 , 0
85518467Sralph 				    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
856766Speter 				    , "_ACTFILE" );
85715934Smckusick 				putRV((char *) 0, cbn , CURFILEOFFSET , NLOCAL ,
85818467Sralph 					PCCTM_PTR|PCCT_STRTY );
85918467Sralph 				putop( PCC_CALL , PCCT_INT );
86018467Sralph 				putop( PCC_CM , PCCT_INT );
86118467Sralph 				putop( PCC_CALL , PCCT_INT );
862766Speter 				putdot( filename , line );
863766Speter 			}
86415935Smckusick 			if (soffset_flag) {
86515935Smckusick 				tmpfree(&soffset);
86615935Smckusick 				soffset_flag = FALSE;
86715935Smckusick 			}
868766Speter 		}
869766Speter 		/*
870766Speter 		 * Done with arguments.
871766Speter 		 * Handle writeln and
872766Speter 		 * insufficent number of args.
873766Speter 		 */
874766Speter 		switch (p->value[0] &~ NSTAND) {
875766Speter 			case O_WRITEF:
876766Speter 				if (argc == 0)
877766Speter 					error("Write requires an argument");
878766Speter 				break;
879766Speter 			case O_MESSAGE:
880766Speter 				if (argc == 0)
881766Speter 					error("Message requires an argument");
882766Speter 			case O_WRITLN:
883766Speter 				if (filetype != nl+T1CHAR)
884766Speter 					error("Can't 'writeln' a non text file");
885766Speter 				if ( opt( 't' ) ) {
88618467Sralph 				    putleaf( PCC_ICON , 0 , 0
88718467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
888766Speter 					, "_WRITLN" );
88915934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
89018467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
891766Speter 				} else {
89218467Sralph 				    putleaf( PCC_ICON , 0 , 0
89318467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
894766Speter 					, "_fputc" );
89518467Sralph 				    putleaf( PCC_ICON , '\n' , 0 , (int) PCCT_CHAR , (char *) 0 );
89618467Sralph 				    putleaf( PCC_ICON , 0 , 0
89718467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
898766Speter 					, "_ACTFILE" );
89915934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
90018467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
90118467Sralph 				    putop( PCC_CALL , PCCT_INT );
90218467Sralph 				    putop( PCC_CM , PCCT_INT );
903766Speter 				}
90418467Sralph 				putop( PCC_CALL , PCCT_INT );
905766Speter 				putdot( filename , line );
906766Speter 				break;
907766Speter 		}
908766Speter 		return;
909766Speter 
910766Speter 	case O_READ4:
911766Speter 	case O_READLN:
912766Speter 		/*
913766Speter 		 * Set up default
914766Speter 		 * file "input".
915766Speter 		 */
916766Speter 		file = NIL;
917766Speter 		filetype = nl+T1CHAR;
918766Speter 		/*
919766Speter 		 * Determine the file implied
920766Speter 		 * for the read and generate
921766Speter 		 * code to make it the active file.
922766Speter 		 */
92315934Smckusick 		if (argv != TR_NIL) {
924766Speter 			codeoff();
92515934Smckusick 			ap = stkrval(argv->list_node.list, NLNIL, (long) RREQ );
926766Speter 			codeon();
92715934Smckusick 			if (ap == NLNIL)
92815934Smckusick 				argv = argv->list_node.next;
92915934Smckusick 			if (ap != NLNIL && ap->class == FILET) {
930766Speter 				/*
931766Speter 				 * Got "read(f, ...", make
932766Speter 				 * f the active file, and save
933766Speter 				 * it and its type for use in
934766Speter 				 * processing the rest of the
935766Speter 				 * arguments to read.
936766Speter 				 */
93715934Smckusick 				file = argv->list_node.list;
938766Speter 				filetype = ap->type;
93915934Smckusick 				putRV((char *) 0, cbn , CURFILEOFFSET , NLOCAL ,
94018467Sralph 					PCCTM_PTR|PCCT_STRTY );
94118467Sralph 				putleaf( PCC_ICON , 0 , 0
94218467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
943766Speter 					, "_UNIT" );
94415934Smckusick 				(void) stklval(argv->list_node.list, NOFLAGS);
94518467Sralph 				putop( PCC_CALL , PCCT_INT );
94618467Sralph 				putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
947766Speter 				putdot( filename , line );
94815934Smckusick 				argv = argv->list_node.next;
949766Speter 				argc--;
950766Speter 			} else {
951766Speter 				/*
952766Speter 				 * Default is read from
953766Speter 				 * standard input.
954766Speter 				 */
95515934Smckusick 				putRV((char *) 0, cbn , CURFILEOFFSET , NLOCAL ,
95618467Sralph 					PCCTM_PTR|PCCT_STRTY );
9573833Speter 				putLV( "_input" , 0 , 0 , NGLOBAL ,
95818467Sralph 					PCCTM_PTR|PCCT_STRTY );
95918467Sralph 				putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
960766Speter 				putdot( filename , line );
961766Speter 				input->nl_flags |= NUSED;
962766Speter 			}
963766Speter 		} else {
96415934Smckusick 			putRV((char *) 0, cbn , CURFILEOFFSET , NLOCAL ,
96518467Sralph 				PCCTM_PTR|PCCT_STRTY );
96618467Sralph 			putLV( "_input" , 0 , 0 , NGLOBAL , PCCTM_PTR|PCCT_STRTY );
96718467Sralph 			putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
968766Speter 			putdot( filename , line );
969766Speter 			input->nl_flags |= NUSED;
970766Speter 		}
971766Speter 		/*
972766Speter 		 * Loop and process each
973766Speter 		 * of the arguments.
974766Speter 		 */
97515934Smckusick 		for (; argv != TR_NIL; argv = argv->list_node.next) {
976766Speter 			/*
977766Speter 			 * Get the address of the target
978766Speter 			 * on the stack.
979766Speter 			 */
98015934Smckusick 			al = argv->list_node.list;
98115934Smckusick 			if (al == TR_NIL)
982766Speter 				continue;
98315934Smckusick 			if (al->tag != T_VAR) {
984766Speter 				error("Arguments to %s must be variables, not expressions", p->symbol);
985766Speter 				continue;
986766Speter 			}
987766Speter 			codeoff();
988766Speter 			ap = stklval(al, MOD|ASGN|NOUSE);
989766Speter 			codeon();
99015934Smckusick 			if (ap == NLNIL)
991766Speter 				continue;
992766Speter 			if (filetype != nl+T1CHAR) {
993766Speter 				/*
994766Speter 				 * Generalized read, i.e.
995766Speter 				 * from a non-textfile.
996766Speter 				 */
99715934Smckusick 				if (incompat(filetype, ap, argv->list_node.list )) {
998766Speter 					error("Type mismatch in read from non-text file");
999766Speter 					continue;
1000766Speter 				}
1001766Speter 				/*
1002766Speter 				 * var := file ^;
1003766Speter 				 */
1004766Speter 				ap = lvalue( al , MOD | ASGN | NOUSE , RREQ );
1005766Speter 				if ( isa( ap , "bsci" ) ) {
1006766Speter 					precheck( ap , "_RANG4" , "_RSNG4" );
1007766Speter 				}
100818467Sralph 				putleaf( PCC_ICON , 0 , 0
100918467Sralph 				    , (int) (PCCM_ADDTYPE(
101018467Sralph 					PCCM_ADDTYPE(
101118467Sralph 					    PCCM_ADDTYPE(
101218467Sralph 						p2type( filetype ) , PCCTM_PTR )
101318467Sralph 					    , PCCTM_FTN )
101418467Sralph 					, PCCTM_PTR ))
1015766Speter 				    , "_FNIL" );
1016766Speter 				if (file != NIL)
101715934Smckusick 					(void) stklval(file, NOFLAGS);
1018766Speter 				else /* Magic */
10193833Speter 					putRV( "_input" , 0 , 0 , NGLOBAL ,
102018467Sralph 						PCCTM_PTR | PCCT_STRTY );
102118467Sralph 				putop(PCC_CALL, PCCM_ADDTYPE(p2type(filetype), PCCTM_PTR));
1022766Speter 				switch ( classify( filetype ) ) {
1023766Speter 				    case TBOOL:
1024766Speter 				    case TCHAR:
1025766Speter 				    case TINT:
1026766Speter 				    case TSCAL:
1027766Speter 				    case TDOUBLE:
1028766Speter 				    case TPTR:
102918467Sralph 					putop( PCCOM_UNARY PCC_MUL
1030766Speter 						, p2type( filetype ) );
1031766Speter 				}
1032766Speter 				switch ( classify( filetype ) ) {
1033766Speter 				    case TBOOL:
1034766Speter 				    case TCHAR:
1035766Speter 				    case TINT:
1036766Speter 				    case TSCAL:
103710373Speter 					    postcheck(ap, filetype);
103810373Speter 					    sconv(p2type(filetype), p2type(ap));
1039766Speter 						/* and fall through */
1040766Speter 				    case TDOUBLE:
1041766Speter 				    case TPTR:
104218467Sralph 					    putop( PCC_ASSIGN , p2type( ap ) );
1043766Speter 					    putdot( filename , line );
1044766Speter 					    break;
1045766Speter 				    default:
104618467Sralph 					    putstrop(PCC_STASG,
104718467Sralph 						    PCCM_ADDTYPE(p2type(ap), PCCTM_PTR),
104815934Smckusick 						    (int) lwidth(ap),
104911856Speter 						    align(ap));
1050766Speter 					    putdot( filename , line );
1051766Speter 					    break;
1052766Speter 				}
1053766Speter 				/*
1054766Speter 				 * get(file);
1055766Speter 				 */
105618467Sralph 				putleaf( PCC_ICON , 0 , 0
105718467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1058766Speter 					, "_GET" );
105915934Smckusick 				putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
106018467Sralph 					PCCTM_PTR|PCCT_STRTY );
106118467Sralph 				putop( PCC_CALL , PCCT_INT );
1062766Speter 				putdot( filename , line );
1063766Speter 				continue;
1064766Speter 			}
1065766Speter 			    /*
1066766Speter 			     *	if you get to here, you are reading from
1067766Speter 			     *	a text file.  only possiblities are:
1068766Speter 			     *	character, integer, real, or scalar.
1069766Speter 			     *	read( f , foo , ... ) is done as
1070766Speter 			     *	foo := read( f ) with rangechecking
1071766Speter 			     *	if appropriate.
1072766Speter 			     */
1073766Speter 			typ = classify(ap);
1074766Speter 			op = rdops(typ);
1075766Speter 			if (op == NIL) {
1076766Speter 				error("Can't read %ss from a text file", clnames[typ]);
1077766Speter 				continue;
1078766Speter 			}
1079766Speter 			    /*
1080766Speter 			     *	left hand side of foo := read( f )
1081766Speter 			     */
1082766Speter 			ap = lvalue( al , MOD|ASGN|NOUSE , RREQ );
1083766Speter 			if ( isa( ap , "bsci" ) ) {
1084766Speter 			    precheck( ap , "_RANG4" , "_RSNG4" );
1085766Speter 			}
1086766Speter 			switch ( op ) {
1087766Speter 			    case O_READC:
1088766Speter 				readname = "_READC";
108918467Sralph 				readtype = PCCT_INT;
1090766Speter 				break;
1091766Speter 			    case O_READ4:
1092766Speter 				readname = "_READ4";
109318467Sralph 				readtype = PCCT_INT;
1094766Speter 				break;
1095766Speter 			    case O_READ8:
1096766Speter 				readname = "_READ8";
109718467Sralph 				readtype = PCCT_DOUBLE;
1098766Speter 				break;
1099766Speter 			    case O_READE:
1100766Speter 				readname = "_READE";
110118467Sralph 				readtype = PCCT_INT;
1102766Speter 				break;
1103766Speter 			}
110418467Sralph 			putleaf( PCC_ICON , 0 , 0
110518467Sralph 				, (int) PCCM_ADDTYPE( PCCTM_FTN | readtype , PCCTM_PTR )
1106766Speter 				, readname );
110715934Smckusick 			putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
110818467Sralph 				PCCTM_PTR|PCCT_STRTY );
1109766Speter 			if ( op == O_READE ) {
1110766Speter 				sprintf( format , PREFIXFORMAT , LABELPREFIX
1111766Speter 					, listnames( ap ) );
111218467Sralph 				putleaf( PCC_ICON , 0, 0, (int) (PCCTM_PTR | PCCT_CHAR),
111315934Smckusick 					format );
111418467Sralph 				putop( PCC_CM , PCCT_INT );
11151629Speter 				warning();
1116766Speter 				if (opt('s')) {
1117766Speter 					standard();
1118766Speter 				}
11191629Speter 				error("Reading scalars from text files is non-standard");
1120766Speter 			}
112118467Sralph 			putop( PCC_CALL , (int) readtype );
1122766Speter 			if ( isa( ap , "bcsi" ) ) {
112318467Sralph 			    postcheck(ap, readtype==PCCT_INT?nl+T4INT:nl+TDOUBLE);
1124766Speter 			}
112515934Smckusick 			sconv((int) readtype, p2type(ap));
112618467Sralph 			putop( PCC_ASSIGN , p2type( ap ) );
1127766Speter 			putdot( filename , line );
1128766Speter 		}
1129766Speter 		/*
1130766Speter 		 * Done with arguments.
1131766Speter 		 * Handle readln and
1132766Speter 		 * insufficient number of args.
1133766Speter 		 */
1134766Speter 		if (p->value[0] == O_READLN) {
1135766Speter 			if (filetype != nl+T1CHAR)
1136766Speter 				error("Can't 'readln' a non text file");
113718467Sralph 			putleaf( PCC_ICON , 0 , 0
113818467Sralph 				, (int) PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1139766Speter 				, "_READLN" );
114015934Smckusick 			putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
114118467Sralph 				PCCTM_PTR|PCCT_STRTY );
114218467Sralph 			putop( PCC_CALL , PCCT_INT );
1143766Speter 			putdot( filename , line );
1144766Speter 		} else if (argc == 0)
1145766Speter 			error("read requires an argument");
1146766Speter 		return;
1147766Speter 
1148766Speter 	case O_GET:
1149766Speter 	case O_PUT:
1150766Speter 		if (argc != 1) {
1151766Speter 			error("%s expects one argument", p->symbol);
1152766Speter 			return;
1153766Speter 		}
115418467Sralph 		putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
115518467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1156766Speter 			, "_UNIT" );
115715934Smckusick 		ap = stklval(argv->list_node.list, NOFLAGS);
115815934Smckusick 		if (ap == NLNIL)
1159766Speter 			return;
1160766Speter 		if (ap->class != FILET) {
1161766Speter 			error("Argument to %s must be a file, not %s", p->symbol, nameof(ap));
1162766Speter 			return;
1163766Speter 		}
116418467Sralph 		putop( PCC_CALL , PCCT_INT );
116518467Sralph 		putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
1166766Speter 		putdot( filename , line );
116718467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1168766Speter 			, op == O_GET ? "_GET" : "_PUT" );
116918467Sralph 		putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
117018467Sralph 		putop( PCC_CALL , PCCT_INT );
1171766Speter 		putdot( filename , line );
1172766Speter 		return;
1173766Speter 
1174766Speter 	case O_RESET:
1175766Speter 	case O_REWRITE:
1176766Speter 		if (argc == 0 || argc > 2) {
1177766Speter 			error("%s expects one or two arguments", p->symbol);
1178766Speter 			return;
1179766Speter 		}
1180766Speter 		if (opt('s') && argc == 2) {
1181766Speter 			standard();
1182766Speter 			error("Two argument forms of reset and rewrite are non-standard");
1183766Speter 		}
118418467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCT_INT
1185766Speter 			, op == O_RESET ? "_RESET" : "_REWRITE" );
118615934Smckusick 		ap = stklval(argv->list_node.list, MOD|NOUSE);
118715934Smckusick 		if (ap == NLNIL)
1188766Speter 			return;
1189766Speter 		if (ap->class != FILET) {
1190766Speter 			error("First argument to %s must be a file, not %s", p->symbol, nameof(ap));
1191766Speter 			return;
1192766Speter 		}
1193766Speter 		if (argc == 2) {
1194766Speter 			/*
1195766Speter 			 * Optional second argument
1196766Speter 			 * is a string name of a
1197766Speter 			 * UNIX (R) file to be associated.
1198766Speter 			 */
119915934Smckusick 			al = argv->list_node.next;
120015934Smckusick 			al = (struct tnode *) stkrval(al->list_node.list,
120115934Smckusick 					NLNIL , (long) RREQ );
120215934Smckusick 			if (al == TR_NIL)
1203766Speter 				return;
120415934Smckusick 			if (classify((struct nl *) al) != TSTR) {
120515934Smckusick 				error("Second argument to %s must be a string, not %s", p->symbol, nameof((struct nl *) al));
1206766Speter 				return;
1207766Speter 			}
120815934Smckusick 			strnglen = width((struct nl *) al);
1209766Speter 		} else {
121018467Sralph 			putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
1211766Speter 			strnglen = 0;
1212766Speter 		}
121318467Sralph 		putop( PCC_CM , PCCT_INT );
121418467Sralph 		putleaf( PCC_ICON , strnglen , 0 , PCCT_INT , (char *) 0 );
121518467Sralph 		putop( PCC_CM , PCCT_INT );
121618467Sralph 		putleaf( PCC_ICON , text(ap) ? 0: width(ap->type) , 0 , PCCT_INT , (char *) 0 );
121718467Sralph 		putop( PCC_CM , PCCT_INT );
121818467Sralph 		putop( PCC_CALL , PCCT_INT );
1219766Speter 		putdot( filename , line );
1220766Speter 		return;
1221766Speter 
1222766Speter 	case O_NEW:
1223766Speter 	case O_DISPOSE:
1224766Speter 		if (argc == 0) {
1225766Speter 			error("%s expects at least one argument", p->symbol);
1226766Speter 			return;
1227766Speter 		}
122815934Smckusick 		alv = argv->list_node.list;
12297967Smckusick 		codeoff();
12309139Smckusick 		ap = stklval(alv, op == O_NEW ? ( MOD | NOUSE ) : MOD );
12317967Smckusick 		codeon();
123215934Smckusick 		if (ap == NLNIL)
1233766Speter 			return;
1234766Speter 		if (ap->class != PTR) {
1235766Speter 			error("(First) argument to %s must be a pointer, not %s", p->symbol, nameof(ap));
1236766Speter 			return;
1237766Speter 		}
1238766Speter 		ap = ap->type;
123915934Smckusick 		if (ap == NLNIL)
1240766Speter 			return;
12419139Smckusick 		if (op == O_NEW)
12429139Smckusick 			cmd = "_NEW";
12439139Smckusick 		else /* op == O_DISPOSE */
12447967Smckusick 			if ((ap->nl_flags & NFILES) != 0)
12457967Smckusick 				cmd = "_DFDISPOSE";
12467967Smckusick 			else
12477967Smckusick 				cmd = "_DISPOSE";
124818467Sralph 		putleaf( PCC_ICON, 0, 0, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ), cmd);
124915934Smckusick 		(void) stklval(alv, op == O_NEW ? ( MOD | NOUSE ) : MOD );
125015934Smckusick 		argv = argv->list_node.next;
125115934Smckusick 		if (argv != TR_NIL) {
1252766Speter 			if (ap->class != RECORD) {
1253766Speter 				error("Record required when specifying variant tags");
1254766Speter 				return;
1255766Speter 			}
125615934Smckusick 			for (; argv != TR_NIL; argv = argv->list_node.next) {
1257766Speter 				if (ap->ptr[NL_VARNT] == NIL) {
1258766Speter 					error("Too many tag fields");
1259766Speter 					return;
1260766Speter 				}
126115934Smckusick 				if (!isconst(argv->list_node.list)) {
1262766Speter 					error("Second and successive arguments to %s must be constants", p->symbol);
1263766Speter 					return;
1264766Speter 				}
126515934Smckusick 				gconst(argv->list_node.list);
1266766Speter 				if (con.ctype == NIL)
1267766Speter 					return;
126815934Smckusick 				if (incompat(con.ctype, (ap->ptr[NL_TAG])->type , TR_NIL )) {
1269766Speter 					cerror("Specified tag constant type clashed with variant case selector type");
1270766Speter 					return;
1271766Speter 				}
1272766Speter 				for (ap = ap->ptr[NL_VARNT]; ap != NIL; ap = ap->chain)
1273766Speter 					if (ap->range[0] == con.crval)
1274766Speter 						break;
1275766Speter 				if (ap == NIL) {
1276766Speter 					error("No variant case label value equals specified constant value");
1277766Speter 					return;
1278766Speter 				}
1279766Speter 				ap = ap->ptr[NL_VTOREC];
1280766Speter 			}
1281766Speter 		}
128218467Sralph 		putleaf( PCC_ICON , width( ap ) , 0 , PCCT_INT , (char *) 0 );
128318467Sralph 		putop( PCC_CM , PCCT_INT );
128418467Sralph 		putop( PCC_CALL , PCCT_INT );
1285766Speter 		putdot( filename , line );
12869139Smckusick 		if (opt('t') && op == O_NEW) {
128718467Sralph 		    putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
12889139Smckusick 			    , "_blkclr" );
128915934Smckusick 		    (void) stkrval(alv, NLNIL , (long) RREQ );
129018467Sralph 		    putleaf( PCC_ICON , width( ap ) , 0 , PCCT_INT , (char *) 0 );
129118467Sralph 		    putop( PCC_CM , PCCT_INT );
129218467Sralph 		    putop( PCC_CALL , PCCT_INT );
12939139Smckusick 		    putdot( filename , line );
12949139Smckusick 		}
1295766Speter 		return;
1296766Speter 
1297766Speter 	case O_DATE:
1298766Speter 	case O_TIME:
1299766Speter 		if (argc != 1) {
1300766Speter 			error("%s expects one argument", p->symbol);
1301766Speter 			return;
1302766Speter 		}
130318467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1304766Speter 			, op == O_DATE ? "_DATE" : "_TIME" );
130515934Smckusick 		ap = stklval(argv->list_node.list, MOD|NOUSE);
1306766Speter 		if (ap == NIL)
1307766Speter 			return;
1308766Speter 		if (classify(ap) != TSTR || width(ap) != 10) {
1309766Speter 			error("Argument to %s must be a alfa, not %s", p->symbol, nameof(ap));
1310766Speter 			return;
1311766Speter 		}
131218467Sralph 		putop( PCC_CALL , PCCT_INT );
1313766Speter 		putdot( filename , line );
1314766Speter 		return;
1315766Speter 
1316766Speter 	case O_HALT:
1317766Speter 		if (argc != 0) {
1318766Speter 			error("halt takes no arguments");
1319766Speter 			return;
1320766Speter 		}
132118467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1322766Speter 			, "_HALT" );
1323766Speter 
132418467Sralph 		putop( PCCOM_UNARY PCC_CALL , PCCT_INT );
1325766Speter 		putdot( filename , line );
132615934Smckusick 		noreach = TRUE;
1327766Speter 		return;
1328766Speter 
1329766Speter 	case O_ARGV:
1330766Speter 		if (argc != 2) {
1331766Speter 			error("argv takes two arguments");
1332766Speter 			return;
1333766Speter 		}
133418467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1335766Speter 			, "_ARGV" );
133615934Smckusick 		ap = stkrval(argv->list_node.list, NLNIL , (long) RREQ );
133715934Smckusick 		if (ap == NLNIL)
1338766Speter 			return;
1339766Speter 		if (isnta(ap, "i")) {
1340766Speter 			error("argv's first argument must be an integer, not %s", nameof(ap));
1341766Speter 			return;
1342766Speter 		}
134315934Smckusick 		al = argv->list_node.next;
134415934Smckusick 		ap = stklval(al->list_node.list, MOD|NOUSE);
134515934Smckusick 		if (ap == NLNIL)
1346766Speter 			return;
1347766Speter 		if (classify(ap) != TSTR) {
1348766Speter 			error("argv's second argument must be a string, not %s", nameof(ap));
1349766Speter 			return;
1350766Speter 		}
135118467Sralph 		putop( PCC_CM , PCCT_INT );
135218467Sralph 		putleaf( PCC_ICON , width( ap ) , 0 , PCCT_INT , (char *) 0 );
135318467Sralph 		putop( PCC_CM , PCCT_INT );
135418467Sralph 		putop( PCC_CALL , PCCT_INT );
1355766Speter 		putdot( filename , line );
1356766Speter 		return;
1357766Speter 
1358766Speter 	case O_STLIM:
1359766Speter 		if (argc != 1) {
1360766Speter 			error("stlimit requires one argument");
1361766Speter 			return;
1362766Speter 		}
136318467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1364766Speter 			, "_STLIM" );
136515934Smckusick 		ap = stkrval(argv->list_node.list, NLNIL , (long) RREQ );
136615934Smckusick 		if (ap == NLNIL)
1367766Speter 			return;
1368766Speter 		if (isnta(ap, "i")) {
1369766Speter 			error("stlimit's argument must be an integer, not %s", nameof(ap));
1370766Speter 			return;
1371766Speter 		}
137218467Sralph 		putop( PCC_CALL , PCCT_INT );
1373766Speter 		putdot( filename , line );
1374766Speter 		return;
1375766Speter 
1376766Speter 	case O_REMOVE:
1377766Speter 		if (argc != 1) {
1378766Speter 			error("remove expects one argument");
1379766Speter 			return;
1380766Speter 		}
138118467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1382766Speter 			, "_REMOVE" );
138315934Smckusick 		ap = stkrval(argv->list_node.list, NLNIL, (long) RREQ );
138415934Smckusick 		if (ap == NLNIL)
1385766Speter 			return;
1386766Speter 		if (classify(ap) != TSTR) {
1387766Speter 			error("remove's argument must be a string, not %s", nameof(ap));
1388766Speter 			return;
1389766Speter 		}
139018467Sralph 		putleaf( PCC_ICON , width( ap ) , 0 , PCCT_INT , (char *) 0 );
139118467Sralph 		putop( PCC_CM , PCCT_INT );
139218467Sralph 		putop( PCC_CALL , PCCT_INT );
1393766Speter 		putdot( filename , line );
1394766Speter 		return;
1395766Speter 
1396766Speter 	case O_LLIMIT:
1397766Speter 		if (argc != 2) {
1398766Speter 			error("linelimit expects two arguments");
1399766Speter 			return;
1400766Speter 		}
140118467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1402766Speter 			, "_LLIMIT" );
140315934Smckusick 		ap = stklval(argv->list_node.list, NOFLAGS|NOUSE);
140415934Smckusick 		if (ap == NLNIL)
1405766Speter 			return;
1406766Speter 		if (!text(ap)) {
1407766Speter 			error("linelimit's first argument must be a text file, not %s", nameof(ap));
1408766Speter 			return;
1409766Speter 		}
141015934Smckusick 		al = argv->list_node.next;
141115934Smckusick 		ap = stkrval(al->list_node.list, NLNIL , (long) RREQ );
141215934Smckusick 		if (ap == NLNIL)
1413766Speter 			return;
1414766Speter 		if (isnta(ap, "i")) {
1415766Speter 			error("linelimit's second argument must be an integer, not %s", nameof(ap));
1416766Speter 			return;
1417766Speter 		}
141818467Sralph 		putop( PCC_CM , PCCT_INT );
141918467Sralph 		putop( PCC_CALL , PCCT_INT );
1420766Speter 		putdot( filename , line );
1421766Speter 		return;
1422766Speter 	case O_PAGE:
1423766Speter 		if (argc != 1) {
1424766Speter 			error("page expects one argument");
1425766Speter 			return;
1426766Speter 		}
142718467Sralph 		putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
142818467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1429766Speter 			, "_UNIT" );
143015934Smckusick 		ap = stklval(argv->list_node.list, NOFLAGS);
143115934Smckusick 		if (ap == NLNIL)
1432766Speter 			return;
1433766Speter 		if (!text(ap)) {
1434766Speter 			error("Argument to page must be a text file, not %s", nameof(ap));
1435766Speter 			return;
1436766Speter 		}
143718467Sralph 		putop( PCC_CALL , PCCT_INT );
143818467Sralph 		putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
1439766Speter 		putdot( filename , line );
1440766Speter 		if ( opt( 't' ) ) {
144118467Sralph 		    putleaf( PCC_ICON , 0 , 0
144218467Sralph 			, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1443766Speter 			, "_PAGE" );
144418467Sralph 		    putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
1445766Speter 		} else {
144618467Sralph 		    putleaf( PCC_ICON , 0 , 0
144718467Sralph 			, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1448766Speter 			, "_fputc" );
144918467Sralph 		    putleaf( PCC_ICON , '\f' , 0 , (int) PCCT_CHAR , (char *) 0 );
145018467Sralph 		    putleaf( PCC_ICON , 0 , 0
145118467Sralph 			, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1452766Speter 			, "_ACTFILE" );
145318467Sralph 		    putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
145418467Sralph 		    putop( PCC_CALL , PCCT_INT );
145518467Sralph 		    putop( PCC_CM , PCCT_INT );
1456766Speter 		}
145718467Sralph 		putop( PCC_CALL , PCCT_INT );
1458766Speter 		putdot( filename , line );
1459766Speter 		return;
1460766Speter 
14617928Smckusick 	case O_ASRT:
14627928Smckusick 		if (!opt('t'))
14637928Smckusick 			return;
14647928Smckusick 		if (argc == 0 || argc > 2) {
14657928Smckusick 			error("Assert expects one or two arguments");
14667928Smckusick 			return;
14677928Smckusick 		}
14689139Smckusick 		if (argc == 2)
14699139Smckusick 			cmd = "_ASRTS";
14709139Smckusick 		else
14719139Smckusick 			cmd = "_ASRT";
147218467Sralph 		putleaf( PCC_ICON , 0 , 0
147318467Sralph 		    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , cmd );
147415934Smckusick 		ap = stkrval(argv->list_node.list, NLNIL , (long) RREQ );
147515934Smckusick 		if (ap == NLNIL)
14767928Smckusick 			return;
14777928Smckusick 		if (isnta(ap, "b"))
14787928Smckusick 			error("Assert expression must be Boolean, not %ss", nameof(ap));
14797928Smckusick 		if (argc == 2) {
14807928Smckusick 			/*
14817928Smckusick 			 * Optional second argument is a string specifying
14827928Smckusick 			 * why the assertion failed.
14837928Smckusick 			 */
148415934Smckusick 			al = argv->list_node.next;
148515934Smckusick 			al = (struct tnode *) stkrval(al->list_node.list, NLNIL , (long) RREQ );
148615934Smckusick 			if (al == TR_NIL)
14877928Smckusick 				return;
148815934Smckusick 			if (classify((struct nl *) al) != TSTR) {
148915934Smckusick 				error("Second argument to assert must be a string, not %s", nameof((struct nl *) al));
14907928Smckusick 				return;
14917928Smckusick 			}
149218467Sralph 			putop( PCC_CM , PCCT_INT );
14937928Smckusick 		}
149418467Sralph 		putop( PCC_CALL , PCCT_INT );
14957928Smckusick 		putdot( filename , line );
14967928Smckusick 		return;
14977928Smckusick 
1498766Speter 	case O_PACK:
1499766Speter 		if (argc != 3) {
1500766Speter 			error("pack expects three arguments");
1501766Speter 			return;
1502766Speter 		}
150318467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1504766Speter 			, "_PACK" );
1505766Speter 		pu = "pack(a,i,z)";
150615934Smckusick 		pua = (al = argv)->list_node.list;
150715934Smckusick 		pui = (al = al->list_node.next)->list_node.list;
150815934Smckusick 		puz = (al = al->list_node.next)->list_node.list;
1509766Speter 		goto packunp;
1510766Speter 	case O_UNPACK:
1511766Speter 		if (argc != 3) {
1512766Speter 			error("unpack expects three arguments");
1513766Speter 			return;
1514766Speter 		}
151518467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1516766Speter 			, "_UNPACK" );
1517766Speter 		pu = "unpack(z,a,i)";
151815934Smckusick 		puz = (al = argv)->list_node.list;
151915934Smckusick 		pua = (al = al->list_node.next)->list_node.list;
152015934Smckusick 		pui = (al = al->list_node.next)->list_node.list;
1521766Speter packunp:
152215934Smckusick 		ap = stkrval(pui, NLNIL , (long) RREQ );
1523766Speter 		if (ap == NIL)
1524766Speter 			return;
1525766Speter 		ap = stklval(pua, op == O_PACK ? NOFLAGS : MOD|NOUSE);
1526766Speter 		if (ap == NIL)
1527766Speter 			return;
1528766Speter 		if (ap->class != ARRAY) {
1529766Speter 			error("%s requires a to be an unpacked array, not %s", pu, nameof(ap));
1530766Speter 			return;
1531766Speter 		}
153218467Sralph 		putop( PCC_CM , PCCT_INT );
153315934Smckusick 		al = (struct tnode *) stklval(puz, op == O_UNPACK ? NOFLAGS : MOD|NOUSE);
153415934Smckusick 		if (((struct nl *) al)->class != ARRAY) {
1535766Speter 			error("%s requires z to be a packed array, not %s", pu, nameof(ap));
1536766Speter 			return;
1537766Speter 		}
153815934Smckusick 		if (((struct nl *) al)->type == NIL ||
153915934Smckusick 			((struct nl *) ap)->type == NIL)
1540766Speter 			return;
154115934Smckusick 		if (((struct nl *) al)->type != ((struct nl *) ap)->type) {
1542766Speter 			error("%s requires a and z to be arrays of the same type", pu, nameof(ap));
1543766Speter 			return;
1544766Speter 		}
154518467Sralph 		putop( PCC_CM , PCCT_INT );
154615934Smckusick 		k = width((struct nl *) al);
1547766Speter 		itemwidth = width(ap->type);
1548766Speter 		ap = ap->chain;
154915934Smckusick 		al = ((struct tnode *) ((struct nl *) al)->chain);
155015934Smckusick 		if (ap->chain != NIL || ((struct nl *) al)->chain != NIL) {
1551766Speter 			error("%s requires a and z to be single dimension arrays", pu);
1552766Speter 			return;
1553766Speter 		}
1554766Speter 		if (ap == NIL || al == NIL)
1555766Speter 			return;
1556766Speter 		/*
1557766Speter 		 * al is the range for z i.e. u..v
1558766Speter 		 * ap is the range for a i.e. m..n
1559766Speter 		 * i will be n-m+1
1560766Speter 		 * j will be v-u+1
1561766Speter 		 */
1562766Speter 		i = ap->range[1] - ap->range[0] + 1;
156315934Smckusick 		j = ((struct nl *) al)->range[1] -
156415934Smckusick 			((struct nl *) al)->range[0] + 1;
1565766Speter 		if (i < j) {
156615934Smckusick 			error("%s cannot have more elements in a (%d) than in z (%d)", pu, (char *) j, (char *) i);
1567766Speter 			return;
1568766Speter 		}
1569766Speter 		/*
1570766Speter 		 * get n-m-(v-u) and m for the interpreter
1571766Speter 		 */
1572766Speter 		i -= j;
1573766Speter 		j = ap->range[0];
157418467Sralph 		putleaf( PCC_ICON , itemwidth , 0 , PCCT_INT , (char *) 0 );
157518467Sralph 		putop( PCC_CM , PCCT_INT );
157618467Sralph 		putleaf( PCC_ICON , j , 0 , PCCT_INT , (char *) 0 );
157718467Sralph 		putop( PCC_CM , PCCT_INT );
157818467Sralph 		putleaf( PCC_ICON , i , 0 , PCCT_INT , (char *) 0 );
157918467Sralph 		putop( PCC_CM , PCCT_INT );
158018467Sralph 		putleaf( PCC_ICON , k , 0 , PCCT_INT , (char *) 0 );
158118467Sralph 		putop( PCC_CM , PCCT_INT );
158218467Sralph 		putop( PCC_CALL , PCCT_INT );
1583766Speter 		putdot( filename , line );
1584766Speter 		return;
1585766Speter 	case 0:
15867928Smckusick 		error("%s is an unimplemented extension", p->symbol);
1587766Speter 		return;
1588766Speter 
1589766Speter 	default:
1590766Speter 		panic("proc case");
1591766Speter 	}
1592766Speter }
1593766Speter #endif PC
1594