xref: /csrg-svn/usr.bin/pascal/src/pcproc.c (revision 18467)
1766Speter /* Copyright (c) 1979 Regents of the University of California */
2766Speter 
315934Smckusick #ifndef lint
4*18467Sralph static	char sccsid[] = "@(#)pcproc.c 2.2 03/20/85";
515934Smckusick #endif
6766Speter 
7766Speter #include "whoami.h"
8766Speter #ifdef PC
9766Speter     /*
10766Speter      * and to the end of the file
11766Speter      */
12766Speter #include "0.h"
13766Speter #include "tree.h"
1410372Speter #include "objfmt.h"
15766Speter #include "opcode.h"
1610372Speter #include "pc.h"
17*18467Sralph #include <pcc.h>
1811333Speter #include "tmps.h"
1915934Smckusick #include "tree_ty.h"
20766Speter 
21766Speter /*
2211883Smckusick  * The constant EXPOSIZE specifies the number of digits in the exponent
2311883Smckusick  * of real numbers.
2411883Smckusick  *
259229Smckusick  * The constant REALSPC defines the amount of forced padding preceeding
269229Smckusick  * real numbers when they are printed. If REALSPC == 0, then no padding
279229Smckusick  * is added, REALSPC == 1 adds one extra blank irregardless of the width
289229Smckusick  * specified by the user.
299229Smckusick  *
309229Smckusick  * N.B. - Values greater than one require program mods.
319229Smckusick  */
3211883Smckusick #define EXPOSIZE	2
3311883Smckusick #define	REALSPC		0
349229Smckusick 
359229Smckusick /*
36766Speter  * The following array is used to determine which classes may be read
37766Speter  * from textfiles. It is indexed by the return value from classify.
38766Speter  */
39766Speter #define rdops(x) rdxxxx[(x)-(TFIRST)]
40766Speter 
41766Speter int rdxxxx[] = {
42766Speter 	0,		/* -7 file types */
43766Speter 	0,		/* -6 record types */
44766Speter 	0,		/* -5 array types */
45766Speter 	O_READE,	/* -4 scalar types */
46766Speter 	0,		/* -3 pointer types */
47766Speter 	0,		/* -2 set types */
48766Speter 	0,		/* -1 string types */
49766Speter 	0,		/*  0 nil, no type */
50766Speter 	O_READE,	/*  1 boolean */
51766Speter 	O_READC,	/*  2 character */
52766Speter 	O_READ4,	/*  3 integer */
53766Speter 	O_READ8		/*  4 real */
54766Speter };
55766Speter 
56766Speter /*
57766Speter  * Proc handles procedure calls.
58766Speter  * Non-builtin procedures are "buck-passed" to func (with a flag
59766Speter  * indicating that they are actually procedures.
60766Speter  * builtin procedures are handled here.
61766Speter  */
62766Speter pcproc(r)
6315934Smckusick 	struct tnode *r;	/* T_PCALL */
64766Speter {
65766Speter 	register struct nl *p;
6615934Smckusick 	register struct tnode *alv, *al;
6715934Smckusick 	register op;
68766Speter 	struct nl *filetype, *ap;
6915934Smckusick 	int argc, typ, fmtspec, strfmt;
7015934Smckusick 	struct tnode *argv, *file;
717967Smckusick 	char fmt, format[20], *strptr, *cmd;
7215934Smckusick 	int prec, field, strnglen, fmtstart;
7315934Smckusick 	char *pu;
7415934Smckusick 	struct tnode *pua, *pui, *puz;
75766Speter 	int i, j, k;
76766Speter 	int itemwidth;
773833Speter 	char		*readname;
783833Speter 	struct nl	*tempnlp;
793833Speter 	long		readtype;
803833Speter 	struct tmps	soffset;
8115935Smckusick 	bool		soffset_flag;
82766Speter 
83766Speter #define	CONPREC 4
84766Speter #define	VARPREC 8
85766Speter #define	CONWIDTH 1
86766Speter #define	VARWIDTH 2
87766Speter #define SKIP 16
88766Speter 
89766Speter 	/*
90766Speter 	 * Verify that the name is
91766Speter 	 * defined and is that of a
92766Speter 	 * procedure.
93766Speter 	 */
9415934Smckusick 	p = lookup(r->pcall_node.proc_id);
9515934Smckusick 	if (p == NLNIL) {
9615934Smckusick 		rvlist(r->pcall_node.arg);
97766Speter 		return;
98766Speter 	}
991197Speter 	if (p->class != PROC && p->class != FPROC) {
100766Speter 		error("Can't call %s, its %s not a procedure", p->symbol, classes[p->class]);
10115934Smckusick 		rvlist(r->pcall_node.arg);
102766Speter 		return;
103766Speter 	}
10415934Smckusick 	argv = r->pcall_node.arg;
105766Speter 
106766Speter 	/*
107766Speter 	 * Call handles user defined
108766Speter 	 * procedures and functions.
109766Speter 	 */
110766Speter 	if (bn != 0) {
11115934Smckusick 		(void) call(p, argv, PROC, bn);
112766Speter 		return;
113766Speter 	}
114766Speter 
115766Speter 	/*
116766Speter 	 * Call to built-in procedure.
117766Speter 	 * Count the arguments.
118766Speter 	 */
119766Speter 	argc = 0;
12015934Smckusick 	for (al = argv; al != TR_NIL; al = al->list_node.next)
121766Speter 		argc++;
122766Speter 
123766Speter 	/*
124766Speter 	 * Switch on the operator
125766Speter 	 * associated with the built-in
126766Speter 	 * procedure in the namelist
127766Speter 	 */
128766Speter 	op = p->value[0] &~ NSTAND;
129766Speter 	if (opt('s') && (p->value[0] & NSTAND)) {
130766Speter 		standard();
131766Speter 		error("%s is a nonstandard procedure", p->symbol);
132766Speter 	}
133766Speter 	switch (op) {
134766Speter 
135766Speter 	case O_ABORT:
136766Speter 		if (argc != 0)
137766Speter 			error("null takes no arguments");
138766Speter 		return;
139766Speter 
140766Speter 	case O_FLUSH:
141766Speter 		if (argc == 0) {
142*18467Sralph 			putleaf( PCC_ICON , 0 , 0 , PCCT_INT , "_PFLUSH" );
143*18467Sralph 			putop( PCCOM_UNARY PCC_CALL , PCCT_INT );
144766Speter 			putdot( filename , line );
145766Speter 			return;
146766Speter 		}
147766Speter 		if (argc != 1) {
148766Speter 			error("flush takes at most one argument");
149766Speter 			return;
150766Speter 		}
151*18467Sralph 		putleaf( PCC_ICON , 0 , 0
152*18467Sralph 			, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
153766Speter 			, "_FLUSH" );
15415934Smckusick 		ap = stklval(argv->list_node.list, NOFLAGS);
15515934Smckusick 		if (ap == NLNIL)
156766Speter 			return;
157766Speter 		if (ap->class != FILET) {
158766Speter 			error("flush's argument must be a file, not %s", nameof(ap));
159766Speter 			return;
160766Speter 		}
161*18467Sralph 		putop( PCC_CALL , PCCT_INT );
162766Speter 		putdot( filename , line );
163766Speter 		return;
164766Speter 
165766Speter 	case O_MESSAGE:
166766Speter 	case O_WRITEF:
167766Speter 	case O_WRITLN:
168766Speter 		/*
169766Speter 		 * Set up default file "output"'s type
170766Speter 		 */
171766Speter 		file = NIL;
172766Speter 		filetype = nl+T1CHAR;
173766Speter 		/*
174766Speter 		 * Determine the file implied
175766Speter 		 * for the write and generate
176766Speter 		 * code to make it the active file.
177766Speter 		 */
178766Speter 		if (op == O_MESSAGE) {
179766Speter 			/*
180766Speter 			 * For message, all that matters
181766Speter 			 * is that the filetype is
182766Speter 			 * a character file.
183766Speter 			 * Thus "output" will suit us fine.
184766Speter 			 */
185*18467Sralph 			putleaf( PCC_ICON , 0 , 0 , PCCT_INT , "_PFLUSH" );
186*18467Sralph 			putop( PCCOM_UNARY PCC_CALL , PCCT_INT );
187766Speter 			putdot( filename , line );
18815934Smckusick 			putRV( (char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
189*18467Sralph 				PCCTM_PTR|PCCT_STRTY );
190*18467Sralph 			putLV( "__err" , 0 , 0 , NGLOBAL , PCCTM_PTR|PCCT_STRTY );
191*18467Sralph 			putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
192766Speter 			putdot( filename , line );
19315934Smckusick 		} else if (argv != TR_NIL && (al = argv->list_node.list)->tag !=
19415934Smckusick 					T_WEXP) {
195766Speter 			/*
196766Speter 			 * If there is a first argument which has
197766Speter 			 * no write widths, then it is potentially
198766Speter 			 * a file name.
199766Speter 			 */
200766Speter 			codeoff();
20115934Smckusick 			ap = stkrval(argv->list_node.list, NLNIL, (long) RREQ );
202766Speter 			codeon();
20315934Smckusick 			if (ap == NLNIL)
20415934Smckusick 				argv = argv->list_node.next;
205766Speter 			if (ap != NIL && ap->class == FILET) {
206766Speter 				/*
207766Speter 				 * Got "write(f, ...", make
208766Speter 				 * f the active file, and save
209766Speter 				 * it and its type for use in
210766Speter 				 * processing the rest of the
211766Speter 				 * arguments to write.
212766Speter 				 */
21315934Smckusick 				putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
214*18467Sralph 					PCCTM_PTR|PCCT_STRTY );
215*18467Sralph 				putleaf( PCC_ICON , 0 , 0
216*18467Sralph 				    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
217766Speter 				    , "_UNIT" );
21815934Smckusick 				file = argv->list_node.list;
219766Speter 				filetype = ap->type;
22015934Smckusick 				(void) stklval(argv->list_node.list, NOFLAGS);
221*18467Sralph 				putop( PCC_CALL , PCCT_INT );
222*18467Sralph 				putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
223766Speter 				putdot( filename , line );
224766Speter 				/*
225766Speter 				 * Skip over the first argument
226766Speter 				 */
22715934Smckusick 				argv = argv->list_node.next;
228766Speter 				argc--;
229766Speter 			} else {
230766Speter 				/*
231766Speter 				 * Set up for writing on
232766Speter 				 * standard output.
233766Speter 				 */
23415934Smckusick 				putRV((char *) 0, cbn , CURFILEOFFSET ,
235*18467Sralph 					NLOCAL , PCCTM_PTR|PCCT_STRTY );
2363833Speter 				putLV( "_output" , 0 , 0 , NGLOBAL ,
237*18467Sralph 					PCCTM_PTR|PCCT_STRTY );
238*18467Sralph 				putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
239766Speter 				putdot( filename , line );
2407954Speter 				output->nl_flags |= NUSED;
241766Speter 			}
242766Speter 		} else {
24315934Smckusick 			putRV((char *) 0, cbn , CURFILEOFFSET , NLOCAL ,
244*18467Sralph 				PCCTM_PTR|PCCT_STRTY );
245*18467Sralph 			putLV( "_output" , 0 , 0 , NGLOBAL , PCCTM_PTR|PCCT_STRTY );
246*18467Sralph 			putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
247766Speter 			putdot( filename , line );
2487954Speter 			output->nl_flags |= NUSED;
249766Speter 		}
250766Speter 		/*
251766Speter 		 * Loop and process each
252766Speter 		 * of the arguments.
253766Speter 		 */
25415934Smckusick 		for (; argv != TR_NIL; argv = argv->list_node.next) {
25515935Smckusick 		        soffset_flag = FALSE;
256766Speter 			/*
257766Speter 			 * fmtspec indicates the type (CONstant or VARiable)
258766Speter 			 *	and number (none, WIDTH, and/or PRECision)
259766Speter 			 *	of the fields in the printf format for this
260766Speter 			 *	output variable.
261766Speter 			 * fmt is the format output indicator (D, E, F, O, X, S)
262766Speter 			 * fmtstart = 0 for leading blank; = 1 for no blank
263766Speter 			 */
264766Speter 			fmtspec = NIL;
265766Speter 			fmt = 'D';
266766Speter 			fmtstart = 1;
26715934Smckusick 			al = argv->list_node.list;
268766Speter 			if (al == NIL)
269766Speter 				continue;
27015934Smckusick 			if (al->tag == T_WEXP)
27115934Smckusick 				alv = al->wexpr_node.expr1;
272766Speter 			else
273766Speter 				alv = al;
27415934Smckusick 			if (alv == TR_NIL)
275766Speter 				continue;
276766Speter 			codeoff();
27715934Smckusick 			ap = stkrval(alv, NLNIL , (long) RREQ );
278766Speter 			codeon();
27915934Smckusick 			if (ap == NLNIL)
280766Speter 				continue;
281766Speter 			typ = classify(ap);
28215934Smckusick 			if (al->tag == T_WEXP) {
283766Speter 				/*
284766Speter 				 * Handle width expressions.
285766Speter 				 * The basic game here is that width
286766Speter 				 * expressions get evaluated. If they
287766Speter 				 * are constant, the value is placed
288766Speter 				 * directly in the format string.
289766Speter 				 * Otherwise the value is pushed onto
290766Speter 				 * the stack and an indirection is
291766Speter 				 * put into the format string.
292766Speter 				 */
29315934Smckusick 				if (al->wexpr_node.expr3 ==
29415934Smckusick 						(struct tnode *) OCT)
295766Speter 					fmt = 'O';
29615934Smckusick 				else if (al->wexpr_node.expr3 ==
29715934Smckusick 						(struct tnode *) HEX)
298766Speter 					fmt = 'X';
29915934Smckusick 				else if (al->wexpr_node.expr3 != TR_NIL) {
300766Speter 					/*
301766Speter 					 * Evaluate second format spec
302766Speter 					 */
30315934Smckusick 					if ( constval(al->wexpr_node.expr3)
304766Speter 					    && isa( con.ctype , "i" ) ) {
305766Speter 						fmtspec += CONPREC;
306766Speter 						prec = con.crval;
307766Speter 					} else {
308766Speter 						fmtspec += VARPREC;
309766Speter 					}
310766Speter 					fmt = 'f';
311766Speter 					switch ( typ ) {
312766Speter 					case TINT:
313766Speter 						if ( opt( 's' ) ) {
314766Speter 						    standard();
315766Speter 						    error("Writing %ss with two write widths is non-standard", clnames[typ]);
316766Speter 						}
317766Speter 						/* and fall through */
318766Speter 					case TDOUBLE:
319766Speter 						break;
320766Speter 					default:
321766Speter 						error("Cannot write %ss with two write widths", clnames[typ]);
322766Speter 						continue;
323766Speter 					}
324766Speter 				}
325766Speter 				/*
326766Speter 				 * Evaluate first format spec
327766Speter 				 */
32815934Smckusick 				if (al->wexpr_node.expr2 != TR_NIL) {
32915934Smckusick 					if ( constval(al->wexpr_node.expr2)
330766Speter 					    && isa( con.ctype , "i" ) ) {
331766Speter 						fmtspec += CONWIDTH;
332766Speter 						field = con.crval;
333766Speter 					} else {
334766Speter 						fmtspec += VARWIDTH;
335766Speter 					}
336766Speter 				}
337766Speter 				if ((fmtspec & CONPREC) && prec < 0 ||
338766Speter 				    (fmtspec & CONWIDTH) && field < 0) {
339766Speter 					error("Negative widths are not allowed");
340766Speter 					continue;
341766Speter 				}
3423180Smckusic 				if ( opt('s') &&
3433180Smckusic 				    ((fmtspec & CONPREC) && prec == 0 ||
3443180Smckusic 				    (fmtspec & CONWIDTH) && field == 0)) {
3453180Smckusic 					standard();
3463180Smckusic 					error("Zero widths are non-standard");
3473180Smckusic 				}
348766Speter 			}
349766Speter 			if (filetype != nl+T1CHAR) {
350766Speter 				if (fmt == 'O' || fmt == 'X') {
351766Speter 					error("Oct/hex allowed only on text files");
352766Speter 					continue;
353766Speter 				}
354766Speter 				if (fmtspec) {
355766Speter 					error("Write widths allowed only on text files");
356766Speter 					continue;
357766Speter 				}
358766Speter 				/*
359766Speter 				 * Generalized write, i.e.
360766Speter 				 * to a non-textfile.
361766Speter 				 */
362*18467Sralph 				putleaf( PCC_ICON , 0 , 0
363*18467Sralph 				    , (int) (PCCM_ADDTYPE(
364*18467Sralph 					PCCM_ADDTYPE(
365*18467Sralph 					    PCCM_ADDTYPE( p2type( filetype )
366*18467Sralph 						    , PCCTM_PTR )
367*18467Sralph 					    , PCCTM_FTN )
368*18467Sralph 					, PCCTM_PTR ))
369766Speter 				    , "_FNIL" );
37015934Smckusick 				(void) stklval(file, NOFLAGS);
371*18467Sralph 				putop( PCC_CALL
372*18467Sralph 				    , PCCM_ADDTYPE( p2type( filetype ) , PCCTM_PTR ) );
373*18467Sralph 				putop( PCCOM_UNARY PCC_MUL , p2type( filetype ) );
374766Speter 				/*
375766Speter 				 * file^ := ...
376766Speter 				 */
377766Speter 				switch ( classify( filetype ) ) {
378766Speter 				    case TBOOL:
379766Speter 				    case TCHAR:
380766Speter 				    case TINT:
381766Speter 				    case TSCAL:
3824589Speter 					precheck( filetype , "_RANG4"  , "_RSNG4" );
383766Speter 					    /* and fall through */
384766Speter 				    case TDOUBLE:
385766Speter 				    case TPTR:
38615934Smckusick 					ap = rvalue( argv->list_node.list , filetype , RREQ );
387766Speter 					break;
388766Speter 				    default:
38915934Smckusick 					ap = rvalue( argv->list_node.list , filetype , LREQ );
390766Speter 					break;
391766Speter 				}
392766Speter 				if (ap == NIL)
393766Speter 					continue;
39415934Smckusick 				if (incompat(ap, filetype, argv->list_node.list)) {
395766Speter 					cerror("Type mismatch in write to non-text file");
396766Speter 					continue;
397766Speter 				}
398766Speter 				switch ( classify( filetype ) ) {
399766Speter 				    case TBOOL:
400766Speter 				    case TCHAR:
401766Speter 				    case TINT:
402766Speter 				    case TSCAL:
40310373Speter 					    postcheck(filetype, ap);
40410373Speter 					    sconv(p2type(ap), p2type(filetype));
405766Speter 						/* and fall through */
406766Speter 				    case TDOUBLE:
407766Speter 				    case TPTR:
408*18467Sralph 					    putop( PCC_ASSIGN , p2type( filetype ) );
409766Speter 					    putdot( filename , line );
410766Speter 					    break;
411766Speter 				    default:
412*18467Sralph 					    putstrop(PCC_STASG,
413*18467Sralph 						    PCCM_ADDTYPE(p2type(filetype),
414*18467Sralph 							    PCCTM_PTR),
41515934Smckusick 						    (int) lwidth(filetype),
41611856Speter 						    align(filetype));
417766Speter 					    putdot( filename , line );
418766Speter 					    break;
419766Speter 				}
420766Speter 				/*
421766Speter 				 * put(file)
422766Speter 				 */
423*18467Sralph 				putleaf( PCC_ICON , 0 , 0
424*18467Sralph 				    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
425766Speter 				    , "_PUT" );
42615934Smckusick 				putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
427*18467Sralph 					PCCTM_PTR|PCCT_STRTY );
428*18467Sralph 				putop( PCC_CALL , PCCT_INT );
429766Speter 				putdot( filename , line );
430766Speter 				continue;
431766Speter 			}
432766Speter 			/*
433766Speter 			 * Write to a textfile
434766Speter 			 *
435766Speter 			 * Evaluate the expression
436766Speter 			 * to be written.
437766Speter 			 */
438766Speter 			if (fmt == 'O' || fmt == 'X') {
439766Speter 				if (opt('s')) {
440766Speter 					standard();
441766Speter 					error("Oct and hex are non-standard");
442766Speter 				}
443766Speter 				if (typ == TSTR || typ == TDOUBLE) {
444766Speter 					error("Can't write %ss with oct/hex", clnames[typ]);
445766Speter 					continue;
446766Speter 				}
447766Speter 				if (typ == TCHAR || typ == TBOOL)
448766Speter 					typ = TINT;
449766Speter 			}
450766Speter 			/*
451766Speter 			 * If there is no format specified by the programmer,
452766Speter 			 * implement the default.
453766Speter 			 */
454766Speter 			switch (typ) {
4556540Smckusick 			case TPTR:
4566540Smckusick 				warning();
4576540Smckusick 				if (opt('s')) {
4586540Smckusick 					standard();
4596540Smckusick 				}
4606540Smckusick 				error("Writing %ss to text files is non-standard",
4616540Smckusick 				    clnames[typ]);
4626540Smckusick 				/* and fall through */
463766Speter 			case TINT:
464766Speter 				if (fmt == 'f') {
465766Speter 					typ = TDOUBLE;
466766Speter 					goto tdouble;
467766Speter 				}
468766Speter 				if (fmtspec == NIL) {
469766Speter 					if (fmt == 'D')
470766Speter 						field = 10;
471766Speter 					else if (fmt == 'X')
472766Speter 						field = 8;
473766Speter 					else if (fmt == 'O')
474766Speter 						field = 11;
475766Speter 					else
476766Speter 						panic("fmt1");
477766Speter 					fmtspec = CONWIDTH;
478766Speter 				}
479766Speter 				break;
480766Speter 			case TCHAR:
481766Speter 			     tchar:
482766Speter 				fmt = 'c';
483766Speter 				break;
484766Speter 			case TSCAL:
4851629Speter 				warning();
486766Speter 				if (opt('s')) {
487766Speter 					standard();
488766Speter 				}
4896540Smckusick 				error("Writing %ss to text files is non-standard",
4906540Smckusick 				    clnames[typ]);
491766Speter 			case TBOOL:
492766Speter 				fmt = 's';
493766Speter 				break;
494766Speter 			case TDOUBLE:
495766Speter 			     tdouble:
496766Speter 				switch (fmtspec) {
497766Speter 				case NIL:
49811883Smckusick 					field = 14 + (5 + EXPOSIZE);
49911883Smckusick 				        prec = field - (5 + EXPOSIZE);
5003225Smckusic 					fmt = 'e';
501766Speter 					fmtspec = CONWIDTH + CONPREC;
502766Speter 					break;
503766Speter 				case CONWIDTH:
5049229Smckusick 					field -= REALSPC;
5059229Smckusick 					if (field < 1)
506766Speter 						field = 1;
50711883Smckusick 				        prec = field - (5 + EXPOSIZE);
508766Speter 					if (prec < 1)
509766Speter 						prec = 1;
510766Speter 					fmtspec += CONPREC;
5113225Smckusic 					fmt = 'e';
512766Speter 					break;
513766Speter 				case VARWIDTH:
514766Speter 					fmtspec += VARPREC;
5153225Smckusic 					fmt = 'e';
516766Speter 					break;
517766Speter 				case CONWIDTH + CONPREC:
518766Speter 				case CONWIDTH + VARPREC:
5199229Smckusick 					field -= REALSPC;
5209229Smckusick 					if (field < 1)
521766Speter 						field = 1;
522766Speter 				}
523766Speter 				format[0] = ' ';
5249229Smckusick 				fmtstart = 1 - REALSPC;
525766Speter 				break;
526766Speter 			case TSTR:
52715934Smckusick 				(void) constval( alv );
528766Speter 				switch ( classify( con.ctype ) ) {
529766Speter 				    case TCHAR:
530766Speter 					typ = TCHAR;
531766Speter 					goto tchar;
532766Speter 				    case TSTR:
533766Speter 					strptr = con.cpval;
534766Speter 					for (strnglen = 0;  *strptr++;  strnglen++) /* void */;
535766Speter 					strptr = con.cpval;
536766Speter 					break;
537766Speter 				    default:
538766Speter 					strnglen = width(ap);
539766Speter 					break;
540766Speter 				}
541766Speter 				fmt = 's';
542766Speter 				strfmt = fmtspec;
543766Speter 				if (fmtspec == NIL) {
544766Speter 					fmtspec = SKIP;
545766Speter 					break;
546766Speter 				}
547766Speter 				if (fmtspec & CONWIDTH) {
548766Speter 					if (field <= strnglen)
549766Speter 						fmtspec = SKIP;
550766Speter 					else
551766Speter 						field -= strnglen;
552766Speter 				}
553766Speter 				break;
554766Speter 			default:
555766Speter 				error("Can't write %ss to a text file", clnames[typ]);
556766Speter 				continue;
557766Speter 			}
558766Speter 			/*
559766Speter 			 * Generate the format string
560766Speter 			 */
561766Speter 			switch (fmtspec) {
562766Speter 			default:
563766Speter 				panic("fmt2");
564766Speter 			case NIL:
565766Speter 				if (fmt == 'c') {
566766Speter 					if ( opt( 't' ) ) {
567*18467Sralph 					    putleaf( PCC_ICON , 0 , 0
568*18467Sralph 						, PCCM_ADDTYPE( PCCTM_FTN|PCCT_INT , PCCTM_PTR )
569766Speter 						, "_WRITEC" );
57015934Smckusick 					    putRV((char *) 0 , cbn , CURFILEOFFSET ,
571*18467Sralph 						    NLOCAL , PCCTM_PTR|PCCT_STRTY );
57215934Smckusick 					    (void) stkrval( alv , NLNIL , (long) RREQ );
573*18467Sralph 					    putop( PCC_CM , PCCT_INT );
574766Speter 					} else {
575*18467Sralph 					    putleaf( PCC_ICON , 0 , 0
576*18467Sralph 						, PCCM_ADDTYPE( PCCTM_FTN|PCCT_INT , PCCTM_PTR )
577766Speter 						, "_fputc" );
57815934Smckusick 					    (void) stkrval( alv , NLNIL ,
57915934Smckusick 							(long) RREQ );
580766Speter 					}
581*18467Sralph 					putleaf( PCC_ICON , 0 , 0
582*18467Sralph 					    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
583766Speter 					    , "_ACTFILE" );
58415934Smckusick 					putRV((char *) 0, cbn , CURFILEOFFSET ,
585*18467Sralph 						NLOCAL , PCCTM_PTR|PCCT_STRTY );
586*18467Sralph 					putop( PCC_CALL , PCCT_INT );
587*18467Sralph 					putop( PCC_CM , PCCT_INT );
588*18467Sralph 					putop( PCC_CALL , PCCT_INT );
589766Speter 					putdot( filename , line );
590766Speter 				} else  {
591766Speter 					sprintf(&format[1], "%%%c", fmt);
592766Speter 					goto fmtgen;
593766Speter 				}
594766Speter 			case SKIP:
595766Speter 				break;
596766Speter 			case CONWIDTH:
597766Speter 				sprintf(&format[1], "%%%1D%c", field, fmt);
598766Speter 				goto fmtgen;
599766Speter 			case VARWIDTH:
600766Speter 				sprintf(&format[1], "%%*%c", fmt);
601766Speter 				goto fmtgen;
602766Speter 			case CONWIDTH + CONPREC:
603766Speter 				sprintf(&format[1], "%%%1D.%1D%c", field, prec, fmt);
604766Speter 				goto fmtgen;
605766Speter 			case CONWIDTH + VARPREC:
606766Speter 				sprintf(&format[1], "%%%1D.*%c", field, fmt);
607766Speter 				goto fmtgen;
608766Speter 			case VARWIDTH + CONPREC:
609766Speter 				sprintf(&format[1], "%%*.%1D%c", prec, fmt);
610766Speter 				goto fmtgen;
611766Speter 			case VARWIDTH + VARPREC:
612766Speter 				sprintf(&format[1], "%%*.*%c", fmt);
613766Speter 			fmtgen:
614766Speter 				if ( opt( 't' ) ) {
615*18467Sralph 				    putleaf( PCC_ICON , 0 , 0
616*18467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
617766Speter 					, "_WRITEF" );
61815934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
619*18467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
620*18467Sralph 				    putleaf( PCC_ICON , 0 , 0
621*18467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
622766Speter 					, "_ACTFILE" );
62315934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
624*18467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
625*18467Sralph 				    putop( PCC_CALL , PCCT_INT );
626*18467Sralph 				    putop( PCC_CM , PCCT_INT );
627766Speter 				} else {
628*18467Sralph 				    putleaf( PCC_ICON , 0 , 0
629*18467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
630766Speter 					, "_fprintf" );
631*18467Sralph 				    putleaf( PCC_ICON , 0 , 0
632*18467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
633766Speter 					, "_ACTFILE" );
63415934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
635*18467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
636*18467Sralph 				    putop( PCC_CALL , PCCT_INT );
637766Speter 				}
638766Speter 				putCONG( &format[ fmtstart ]
639766Speter 					, strlen( &format[ fmtstart ] )
640766Speter 					, LREQ );
641*18467Sralph 				putop( PCC_CM , PCCT_INT );
642766Speter 				if ( fmtspec & VARWIDTH ) {
643766Speter 					/*
644766Speter 					 * either
645766Speter 					 *	,(temp=width,MAX(temp,...)),
646766Speter 					 * or
647766Speter 					 *	, MAX( width , ... ) ,
648766Speter 					 */
64915934Smckusick 				    if ( ( typ == TDOUBLE &&
65015934Smckusick 						al->wexpr_node.expr3 == TR_NIL )
651766Speter 					|| typ == TSTR ) {
65215935Smckusick 					soffset_flag = TRUE;
6533225Smckusic 					soffset = sizes[cbn].curtmps;
65415934Smckusick 					tempnlp = tmpalloc((long) (sizeof(long)),
6553225Smckusic 						nl+T4INT, REGOK);
65615934Smckusick 					putRV((char *) 0 , cbn ,
6573833Speter 					    tempnlp -> value[ NL_OFFS ] ,
658*18467Sralph 					    tempnlp -> extra_flags , PCCT_INT );
65915934Smckusick 					ap = stkrval( al->wexpr_node.expr2 ,
66015934Smckusick 						NLNIL , (long) RREQ );
661*18467Sralph 					putop( PCC_ASSIGN , PCCT_INT );
662*18467Sralph 					putleaf( PCC_ICON , 0 , 0
663*18467Sralph 					    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
664766Speter 					    , "_MAX" );
66515934Smckusick 					putRV((char *) 0 , cbn ,
6663833Speter 					    tempnlp -> value[ NL_OFFS ] ,
667*18467Sralph 					    tempnlp -> extra_flags , PCCT_INT );
668766Speter 				    } else {
669766Speter 					if (opt('t')
670766Speter 					    || typ == TSTR || typ == TDOUBLE) {
671*18467Sralph 					    putleaf( PCC_ICON , 0 , 0
672*18467Sralph 						,PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT, PCCTM_PTR )
673766Speter 						,"_MAX" );
674766Speter 					}
67515934Smckusick 					ap = stkrval( al->wexpr_node.expr2,
67615934Smckusick 						NLNIL , (long) RREQ );
677766Speter 				    }
67815934Smckusick 				    if (ap == NLNIL)
679766Speter 					    continue;
680766Speter 				    if (isnta(ap,"i")) {
681766Speter 					    error("First write width must be integer, not %s", nameof(ap));
682766Speter 					    continue;
683766Speter 				    }
684766Speter 				    switch ( typ ) {
685766Speter 				    case TDOUBLE:
686*18467Sralph 					putleaf( PCC_ICON , REALSPC , 0 , PCCT_INT , (char *) 0 );
687*18467Sralph 					putop( PCC_CM , PCCT_INT );
688*18467Sralph 					putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 );
689*18467Sralph 					putop( PCC_CM , PCCT_INT );
690*18467Sralph 					putop( PCC_CALL , PCCT_INT );
69115934Smckusick 					if ( al->wexpr_node.expr3 == TR_NIL ) {
692766Speter 						/*
693766Speter 						 * finish up the comma op
694766Speter 						 */
695*18467Sralph 					    putop( PCC_COMOP , PCCT_INT );
696766Speter 					    fmtspec &= ~VARPREC;
697*18467Sralph 					    putop( PCC_CM , PCCT_INT );
698*18467Sralph 					    putleaf( PCC_ICON , 0 , 0
699*18467Sralph 						, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
700766Speter 						, "_MAX" );
70115934Smckusick 					    putRV((char *) 0 , cbn ,
7023833Speter 						tempnlp -> value[ NL_OFFS ] ,
7033833Speter 						tempnlp -> extra_flags ,
704*18467Sralph 						PCCT_INT );
705*18467Sralph 					    putleaf( PCC_ICON ,
70611883Smckusick 						5 + EXPOSIZE + REALSPC ,
707*18467Sralph 						0 , PCCT_INT , (char *) 0 );
708*18467Sralph 					    putop( PCC_CM , PCCT_INT );
709*18467Sralph 					    putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 );
710*18467Sralph 					    putop( PCC_CM , PCCT_INT );
711*18467Sralph 					    putop( PCC_CALL , PCCT_INT );
712766Speter 					}
713*18467Sralph 					putop( PCC_CM , PCCT_INT );
714766Speter 					break;
715766Speter 				    case TSTR:
716*18467Sralph 					putleaf( PCC_ICON , strnglen , 0 , PCCT_INT , (char *) 0 );
717*18467Sralph 					putop( PCC_CM , PCCT_INT );
718*18467Sralph 					putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
719*18467Sralph 					putop( PCC_CM , PCCT_INT );
720*18467Sralph 					putop( PCC_CALL , PCCT_INT );
721*18467Sralph 					putop( PCC_COMOP , PCCT_INT );
722*18467Sralph 					putop( PCC_CM , PCCT_INT );
723766Speter 					break;
724766Speter 				    default:
725766Speter 					if (opt('t')) {
726*18467Sralph 					    putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
727*18467Sralph 					    putop( PCC_CM , PCCT_INT );
728*18467Sralph 					    putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
729*18467Sralph 					    putop( PCC_CM , PCCT_INT );
730*18467Sralph 					    putop( PCC_CALL , PCCT_INT );
731766Speter 					}
732*18467Sralph 					putop( PCC_CM , PCCT_INT );
733766Speter 					break;
734766Speter 				    }
735766Speter 				}
736766Speter 				/*
737766Speter 				 * If there is a variable precision,
738766Speter 				 * evaluate it
739766Speter 				 */
740766Speter 				if (fmtspec & VARPREC) {
741766Speter 					if (opt('t')) {
742*18467Sralph 					putleaf( PCC_ICON , 0 , 0
743*18467Sralph 					    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
744766Speter 					    , "_MAX" );
745766Speter 					}
74615934Smckusick 					ap = stkrval( al->wexpr_node.expr3 ,
74715934Smckusick 						NLNIL , (long) RREQ );
748766Speter 					if (ap == NIL)
749766Speter 						continue;
750766Speter 					if (isnta(ap,"i")) {
751766Speter 						error("Second write width must be integer, not %s", nameof(ap));
752766Speter 						continue;
753766Speter 					}
754766Speter 					if (opt('t')) {
755*18467Sralph 					    putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
756*18467Sralph 					    putop( PCC_CM , PCCT_INT );
757*18467Sralph 					    putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
758*18467Sralph 					    putop( PCC_CM , PCCT_INT );
759*18467Sralph 					    putop( PCC_CALL , PCCT_INT );
760766Speter 					}
761*18467Sralph 				 	putop( PCC_CM , PCCT_INT );
762766Speter 				}
763766Speter 				/*
764766Speter 				 * evaluate the thing we want printed.
765766Speter 				 */
766766Speter 				switch ( typ ) {
7676540Smckusick 				case TPTR:
768766Speter 				case TCHAR:
769766Speter 				case TINT:
77015934Smckusick 				    (void) stkrval( alv , NLNIL , (long) RREQ );
771*18467Sralph 				    putop( PCC_CM , PCCT_INT );
772766Speter 				    break;
773766Speter 				case TDOUBLE:
77415934Smckusick 				    ap = stkrval( alv , NLNIL , (long) RREQ );
77510373Speter 				    if (isnta(ap, "d")) {
776*18467Sralph 					sconv(p2type(ap), PCCT_DOUBLE);
777766Speter 				    }
778*18467Sralph 				    putop( PCC_CM , PCCT_INT );
779766Speter 				    break;
780766Speter 				case TSCAL:
781766Speter 				case TBOOL:
782*18467Sralph 				    putleaf( PCC_ICON , 0 , 0
783*18467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
784766Speter 					, "_NAM" );
78515934Smckusick 				    ap = stkrval( alv , NLNIL , (long) RREQ );
786766Speter 				    sprintf( format , PREFIXFORMAT , LABELPREFIX
787766Speter 					    , listnames( ap ) );
788*18467Sralph 				    putleaf( PCC_ICON , 0 , 0 ,
789*18467Sralph 					(int) (PCCTM_PTR | PCCT_CHAR), format );
790*18467Sralph 				    putop( PCC_CM , PCCT_INT );
791*18467Sralph 				    putop( PCC_CALL , PCCT_INT );
792*18467Sralph 				    putop( PCC_CM , PCCT_INT );
793766Speter 				    break;
794766Speter 				case TSTR:
795766Speter 				    putCONG( "" , 0 , LREQ );
796*18467Sralph 				    putop( PCC_CM , PCCT_INT );
797766Speter 				    break;
7986540Smckusick 				default:
7996540Smckusick 				    panic("fmt3");
8006540Smckusick 				    break;
801766Speter 				}
802*18467Sralph 				putop( PCC_CALL , PCCT_INT );
803766Speter 				putdot( filename , line );
804766Speter 			}
805766Speter 			/*
806766Speter 			 * Write the string after its blank padding
807766Speter 			 */
808766Speter 			if (typ == TSTR ) {
809766Speter 				if ( opt( 't' ) ) {
810*18467Sralph 				    putleaf( PCC_ICON , 0 , 0
811*18467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
812766Speter 					, "_WRITES" );
81315934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
814*18467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
81515934Smckusick 				    ap = stkrval(alv, NLNIL , (long) RREQ );
816*18467Sralph 				    putop( PCC_CM , PCCT_INT );
817766Speter 				} else {
818*18467Sralph 				    putleaf( PCC_ICON , 0 , 0
819*18467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
820766Speter 					, "_fwrite" );
82115934Smckusick 				    ap = stkrval(alv, NLNIL , (long) RREQ );
822766Speter 				}
823766Speter 				if (strfmt & VARWIDTH) {
824766Speter 					    /*
825766Speter 					     *	min, inline expanded as
826766Speter 					     *	temp < len ? temp : len
827766Speter 					     */
82815934Smckusick 					putRV((char *) 0 , cbn ,
8293833Speter 					    tempnlp -> value[ NL_OFFS ] ,
830*18467Sralph 					    tempnlp -> extra_flags , PCCT_INT );
831*18467Sralph 					putleaf( PCC_ICON , strnglen , 0 , PCCT_INT , (char *) 0 );
832*18467Sralph 					putop( PCC_LT , PCCT_INT );
83315934Smckusick 					putRV((char *) 0 , cbn ,
8343833Speter 					    tempnlp -> value[ NL_OFFS ] ,
835*18467Sralph 					    tempnlp -> extra_flags , PCCT_INT );
836*18467Sralph 					putleaf( PCC_ICON , strnglen , 0 , PCCT_INT , (char *) 0 );
837*18467Sralph 					putop( PCC_COLON , PCCT_INT );
838*18467Sralph 					putop( PCC_QUEST , PCCT_INT );
839766Speter 				} else {
840766Speter 					if (   ( fmtspec & SKIP )
841766Speter 					    && ( strfmt & CONWIDTH ) ) {
842766Speter 						strnglen = field;
843766Speter 					}
844*18467Sralph 					putleaf( PCC_ICON , strnglen , 0 , PCCT_INT , (char *) 0 );
845766Speter 				}
846*18467Sralph 				putop( PCC_CM , PCCT_INT );
847*18467Sralph 				putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 );
848*18467Sralph 				putop( PCC_CM , PCCT_INT );
849*18467Sralph 				putleaf( PCC_ICON , 0 , 0
850*18467Sralph 				    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
851766Speter 				    , "_ACTFILE" );
85215934Smckusick 				putRV((char *) 0, cbn , CURFILEOFFSET , NLOCAL ,
853*18467Sralph 					PCCTM_PTR|PCCT_STRTY );
854*18467Sralph 				putop( PCC_CALL , PCCT_INT );
855*18467Sralph 				putop( PCC_CM , PCCT_INT );
856*18467Sralph 				putop( PCC_CALL , PCCT_INT );
857766Speter 				putdot( filename , line );
858766Speter 			}
85915935Smckusick 			if (soffset_flag) {
86015935Smckusick 				tmpfree(&soffset);
86115935Smckusick 				soffset_flag = FALSE;
86215935Smckusick 			}
863766Speter 		}
864766Speter 		/*
865766Speter 		 * Done with arguments.
866766Speter 		 * Handle writeln and
867766Speter 		 * insufficent number of args.
868766Speter 		 */
869766Speter 		switch (p->value[0] &~ NSTAND) {
870766Speter 			case O_WRITEF:
871766Speter 				if (argc == 0)
872766Speter 					error("Write requires an argument");
873766Speter 				break;
874766Speter 			case O_MESSAGE:
875766Speter 				if (argc == 0)
876766Speter 					error("Message requires an argument");
877766Speter 			case O_WRITLN:
878766Speter 				if (filetype != nl+T1CHAR)
879766Speter 					error("Can't 'writeln' a non text file");
880766Speter 				if ( opt( 't' ) ) {
881*18467Sralph 				    putleaf( PCC_ICON , 0 , 0
882*18467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
883766Speter 					, "_WRITLN" );
88415934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
885*18467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
886766Speter 				} else {
887*18467Sralph 				    putleaf( PCC_ICON , 0 , 0
888*18467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
889766Speter 					, "_fputc" );
890*18467Sralph 				    putleaf( PCC_ICON , '\n' , 0 , (int) PCCT_CHAR , (char *) 0 );
891*18467Sralph 				    putleaf( PCC_ICON , 0 , 0
892*18467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
893766Speter 					, "_ACTFILE" );
89415934Smckusick 				    putRV((char *) 0 , cbn , CURFILEOFFSET ,
895*18467Sralph 					    NLOCAL , PCCTM_PTR|PCCT_STRTY );
896*18467Sralph 				    putop( PCC_CALL , PCCT_INT );
897*18467Sralph 				    putop( PCC_CM , PCCT_INT );
898766Speter 				}
899*18467Sralph 				putop( PCC_CALL , PCCT_INT );
900766Speter 				putdot( filename , line );
901766Speter 				break;
902766Speter 		}
903766Speter 		return;
904766Speter 
905766Speter 	case O_READ4:
906766Speter 	case O_READLN:
907766Speter 		/*
908766Speter 		 * Set up default
909766Speter 		 * file "input".
910766Speter 		 */
911766Speter 		file = NIL;
912766Speter 		filetype = nl+T1CHAR;
913766Speter 		/*
914766Speter 		 * Determine the file implied
915766Speter 		 * for the read and generate
916766Speter 		 * code to make it the active file.
917766Speter 		 */
91815934Smckusick 		if (argv != TR_NIL) {
919766Speter 			codeoff();
92015934Smckusick 			ap = stkrval(argv->list_node.list, NLNIL, (long) RREQ );
921766Speter 			codeon();
92215934Smckusick 			if (ap == NLNIL)
92315934Smckusick 				argv = argv->list_node.next;
92415934Smckusick 			if (ap != NLNIL && ap->class == FILET) {
925766Speter 				/*
926766Speter 				 * Got "read(f, ...", make
927766Speter 				 * f the active file, and save
928766Speter 				 * it and its type for use in
929766Speter 				 * processing the rest of the
930766Speter 				 * arguments to read.
931766Speter 				 */
93215934Smckusick 				file = argv->list_node.list;
933766Speter 				filetype = ap->type;
93415934Smckusick 				putRV((char *) 0, cbn , CURFILEOFFSET , NLOCAL ,
935*18467Sralph 					PCCTM_PTR|PCCT_STRTY );
936*18467Sralph 				putleaf( PCC_ICON , 0 , 0
937*18467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
938766Speter 					, "_UNIT" );
93915934Smckusick 				(void) stklval(argv->list_node.list, NOFLAGS);
940*18467Sralph 				putop( PCC_CALL , PCCT_INT );
941*18467Sralph 				putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
942766Speter 				putdot( filename , line );
94315934Smckusick 				argv = argv->list_node.next;
944766Speter 				argc--;
945766Speter 			} else {
946766Speter 				/*
947766Speter 				 * Default is read from
948766Speter 				 * standard input.
949766Speter 				 */
95015934Smckusick 				putRV((char *) 0, cbn , CURFILEOFFSET , NLOCAL ,
951*18467Sralph 					PCCTM_PTR|PCCT_STRTY );
9523833Speter 				putLV( "_input" , 0 , 0 , NGLOBAL ,
953*18467Sralph 					PCCTM_PTR|PCCT_STRTY );
954*18467Sralph 				putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
955766Speter 				putdot( filename , line );
956766Speter 				input->nl_flags |= NUSED;
957766Speter 			}
958766Speter 		} else {
95915934Smckusick 			putRV((char *) 0, cbn , CURFILEOFFSET , NLOCAL ,
960*18467Sralph 				PCCTM_PTR|PCCT_STRTY );
961*18467Sralph 			putLV( "_input" , 0 , 0 , NGLOBAL , PCCTM_PTR|PCCT_STRTY );
962*18467Sralph 			putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
963766Speter 			putdot( filename , line );
964766Speter 			input->nl_flags |= NUSED;
965766Speter 		}
966766Speter 		/*
967766Speter 		 * Loop and process each
968766Speter 		 * of the arguments.
969766Speter 		 */
97015934Smckusick 		for (; argv != TR_NIL; argv = argv->list_node.next) {
971766Speter 			/*
972766Speter 			 * Get the address of the target
973766Speter 			 * on the stack.
974766Speter 			 */
97515934Smckusick 			al = argv->list_node.list;
97615934Smckusick 			if (al == TR_NIL)
977766Speter 				continue;
97815934Smckusick 			if (al->tag != T_VAR) {
979766Speter 				error("Arguments to %s must be variables, not expressions", p->symbol);
980766Speter 				continue;
981766Speter 			}
982766Speter 			codeoff();
983766Speter 			ap = stklval(al, MOD|ASGN|NOUSE);
984766Speter 			codeon();
98515934Smckusick 			if (ap == NLNIL)
986766Speter 				continue;
987766Speter 			if (filetype != nl+T1CHAR) {
988766Speter 				/*
989766Speter 				 * Generalized read, i.e.
990766Speter 				 * from a non-textfile.
991766Speter 				 */
99215934Smckusick 				if (incompat(filetype, ap, argv->list_node.list )) {
993766Speter 					error("Type mismatch in read from non-text file");
994766Speter 					continue;
995766Speter 				}
996766Speter 				/*
997766Speter 				 * var := file ^;
998766Speter 				 */
999766Speter 				ap = lvalue( al , MOD | ASGN | NOUSE , RREQ );
1000766Speter 				if ( isa( ap , "bsci" ) ) {
1001766Speter 					precheck( ap , "_RANG4" , "_RSNG4" );
1002766Speter 				}
1003*18467Sralph 				putleaf( PCC_ICON , 0 , 0
1004*18467Sralph 				    , (int) (PCCM_ADDTYPE(
1005*18467Sralph 					PCCM_ADDTYPE(
1006*18467Sralph 					    PCCM_ADDTYPE(
1007*18467Sralph 						p2type( filetype ) , PCCTM_PTR )
1008*18467Sralph 					    , PCCTM_FTN )
1009*18467Sralph 					, PCCTM_PTR ))
1010766Speter 				    , "_FNIL" );
1011766Speter 				if (file != NIL)
101215934Smckusick 					(void) stklval(file, NOFLAGS);
1013766Speter 				else /* Magic */
10143833Speter 					putRV( "_input" , 0 , 0 , NGLOBAL ,
1015*18467Sralph 						PCCTM_PTR | PCCT_STRTY );
1016*18467Sralph 				putop(PCC_CALL, PCCM_ADDTYPE(p2type(filetype), PCCTM_PTR));
1017766Speter 				switch ( classify( filetype ) ) {
1018766Speter 				    case TBOOL:
1019766Speter 				    case TCHAR:
1020766Speter 				    case TINT:
1021766Speter 				    case TSCAL:
1022766Speter 				    case TDOUBLE:
1023766Speter 				    case TPTR:
1024*18467Sralph 					putop( PCCOM_UNARY PCC_MUL
1025766Speter 						, p2type( filetype ) );
1026766Speter 				}
1027766Speter 				switch ( classify( filetype ) ) {
1028766Speter 				    case TBOOL:
1029766Speter 				    case TCHAR:
1030766Speter 				    case TINT:
1031766Speter 				    case TSCAL:
103210373Speter 					    postcheck(ap, filetype);
103310373Speter 					    sconv(p2type(filetype), p2type(ap));
1034766Speter 						/* and fall through */
1035766Speter 				    case TDOUBLE:
1036766Speter 				    case TPTR:
1037*18467Sralph 					    putop( PCC_ASSIGN , p2type( ap ) );
1038766Speter 					    putdot( filename , line );
1039766Speter 					    break;
1040766Speter 				    default:
1041*18467Sralph 					    putstrop(PCC_STASG,
1042*18467Sralph 						    PCCM_ADDTYPE(p2type(ap), PCCTM_PTR),
104315934Smckusick 						    (int) lwidth(ap),
104411856Speter 						    align(ap));
1045766Speter 					    putdot( filename , line );
1046766Speter 					    break;
1047766Speter 				}
1048766Speter 				/*
1049766Speter 				 * get(file);
1050766Speter 				 */
1051*18467Sralph 				putleaf( PCC_ICON , 0 , 0
1052*18467Sralph 					, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1053766Speter 					, "_GET" );
105415934Smckusick 				putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
1055*18467Sralph 					PCCTM_PTR|PCCT_STRTY );
1056*18467Sralph 				putop( PCC_CALL , PCCT_INT );
1057766Speter 				putdot( filename , line );
1058766Speter 				continue;
1059766Speter 			}
1060766Speter 			    /*
1061766Speter 			     *	if you get to here, you are reading from
1062766Speter 			     *	a text file.  only possiblities are:
1063766Speter 			     *	character, integer, real, or scalar.
1064766Speter 			     *	read( f , foo , ... ) is done as
1065766Speter 			     *	foo := read( f ) with rangechecking
1066766Speter 			     *	if appropriate.
1067766Speter 			     */
1068766Speter 			typ = classify(ap);
1069766Speter 			op = rdops(typ);
1070766Speter 			if (op == NIL) {
1071766Speter 				error("Can't read %ss from a text file", clnames[typ]);
1072766Speter 				continue;
1073766Speter 			}
1074766Speter 			    /*
1075766Speter 			     *	left hand side of foo := read( f )
1076766Speter 			     */
1077766Speter 			ap = lvalue( al , MOD|ASGN|NOUSE , RREQ );
1078766Speter 			if ( isa( ap , "bsci" ) ) {
1079766Speter 			    precheck( ap , "_RANG4" , "_RSNG4" );
1080766Speter 			}
1081766Speter 			switch ( op ) {
1082766Speter 			    case O_READC:
1083766Speter 				readname = "_READC";
1084*18467Sralph 				readtype = PCCT_INT;
1085766Speter 				break;
1086766Speter 			    case O_READ4:
1087766Speter 				readname = "_READ4";
1088*18467Sralph 				readtype = PCCT_INT;
1089766Speter 				break;
1090766Speter 			    case O_READ8:
1091766Speter 				readname = "_READ8";
1092*18467Sralph 				readtype = PCCT_DOUBLE;
1093766Speter 				break;
1094766Speter 			    case O_READE:
1095766Speter 				readname = "_READE";
1096*18467Sralph 				readtype = PCCT_INT;
1097766Speter 				break;
1098766Speter 			}
1099*18467Sralph 			putleaf( PCC_ICON , 0 , 0
1100*18467Sralph 				, (int) PCCM_ADDTYPE( PCCTM_FTN | readtype , PCCTM_PTR )
1101766Speter 				, readname );
110215934Smckusick 			putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
1103*18467Sralph 				PCCTM_PTR|PCCT_STRTY );
1104766Speter 			if ( op == O_READE ) {
1105766Speter 				sprintf( format , PREFIXFORMAT , LABELPREFIX
1106766Speter 					, listnames( ap ) );
1107*18467Sralph 				putleaf( PCC_ICON , 0, 0, (int) (PCCTM_PTR | PCCT_CHAR),
110815934Smckusick 					format );
1109*18467Sralph 				putop( PCC_CM , PCCT_INT );
11101629Speter 				warning();
1111766Speter 				if (opt('s')) {
1112766Speter 					standard();
1113766Speter 				}
11141629Speter 				error("Reading scalars from text files is non-standard");
1115766Speter 			}
1116*18467Sralph 			putop( PCC_CALL , (int) readtype );
1117766Speter 			if ( isa( ap , "bcsi" ) ) {
1118*18467Sralph 			    postcheck(ap, readtype==PCCT_INT?nl+T4INT:nl+TDOUBLE);
1119766Speter 			}
112015934Smckusick 			sconv((int) readtype, p2type(ap));
1121*18467Sralph 			putop( PCC_ASSIGN , p2type( ap ) );
1122766Speter 			putdot( filename , line );
1123766Speter 		}
1124766Speter 		/*
1125766Speter 		 * Done with arguments.
1126766Speter 		 * Handle readln and
1127766Speter 		 * insufficient number of args.
1128766Speter 		 */
1129766Speter 		if (p->value[0] == O_READLN) {
1130766Speter 			if (filetype != nl+T1CHAR)
1131766Speter 				error("Can't 'readln' a non text file");
1132*18467Sralph 			putleaf( PCC_ICON , 0 , 0
1133*18467Sralph 				, (int) PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1134766Speter 				, "_READLN" );
113515934Smckusick 			putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL ,
1136*18467Sralph 				PCCTM_PTR|PCCT_STRTY );
1137*18467Sralph 			putop( PCC_CALL , PCCT_INT );
1138766Speter 			putdot( filename , line );
1139766Speter 		} else if (argc == 0)
1140766Speter 			error("read requires an argument");
1141766Speter 		return;
1142766Speter 
1143766Speter 	case O_GET:
1144766Speter 	case O_PUT:
1145766Speter 		if (argc != 1) {
1146766Speter 			error("%s expects one argument", p->symbol);
1147766Speter 			return;
1148766Speter 		}
1149*18467Sralph 		putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
1150*18467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1151766Speter 			, "_UNIT" );
115215934Smckusick 		ap = stklval(argv->list_node.list, NOFLAGS);
115315934Smckusick 		if (ap == NLNIL)
1154766Speter 			return;
1155766Speter 		if (ap->class != FILET) {
1156766Speter 			error("Argument to %s must be a file, not %s", p->symbol, nameof(ap));
1157766Speter 			return;
1158766Speter 		}
1159*18467Sralph 		putop( PCC_CALL , PCCT_INT );
1160*18467Sralph 		putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
1161766Speter 		putdot( filename , line );
1162*18467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1163766Speter 			, op == O_GET ? "_GET" : "_PUT" );
1164*18467Sralph 		putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
1165*18467Sralph 		putop( PCC_CALL , PCCT_INT );
1166766Speter 		putdot( filename , line );
1167766Speter 		return;
1168766Speter 
1169766Speter 	case O_RESET:
1170766Speter 	case O_REWRITE:
1171766Speter 		if (argc == 0 || argc > 2) {
1172766Speter 			error("%s expects one or two arguments", p->symbol);
1173766Speter 			return;
1174766Speter 		}
1175766Speter 		if (opt('s') && argc == 2) {
1176766Speter 			standard();
1177766Speter 			error("Two argument forms of reset and rewrite are non-standard");
1178766Speter 		}
1179*18467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCT_INT
1180766Speter 			, op == O_RESET ? "_RESET" : "_REWRITE" );
118115934Smckusick 		ap = stklval(argv->list_node.list, MOD|NOUSE);
118215934Smckusick 		if (ap == NLNIL)
1183766Speter 			return;
1184766Speter 		if (ap->class != FILET) {
1185766Speter 			error("First argument to %s must be a file, not %s", p->symbol, nameof(ap));
1186766Speter 			return;
1187766Speter 		}
1188766Speter 		if (argc == 2) {
1189766Speter 			/*
1190766Speter 			 * Optional second argument
1191766Speter 			 * is a string name of a
1192766Speter 			 * UNIX (R) file to be associated.
1193766Speter 			 */
119415934Smckusick 			al = argv->list_node.next;
119515934Smckusick 			al = (struct tnode *) stkrval(al->list_node.list,
119615934Smckusick 					NLNIL , (long) RREQ );
119715934Smckusick 			if (al == TR_NIL)
1198766Speter 				return;
119915934Smckusick 			if (classify((struct nl *) al) != TSTR) {
120015934Smckusick 				error("Second argument to %s must be a string, not %s", p->symbol, nameof((struct nl *) al));
1201766Speter 				return;
1202766Speter 			}
120315934Smckusick 			strnglen = width((struct nl *) al);
1204766Speter 		} else {
1205*18467Sralph 			putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
1206766Speter 			strnglen = 0;
1207766Speter 		}
1208*18467Sralph 		putop( PCC_CM , PCCT_INT );
1209*18467Sralph 		putleaf( PCC_ICON , strnglen , 0 , PCCT_INT , (char *) 0 );
1210*18467Sralph 		putop( PCC_CM , PCCT_INT );
1211*18467Sralph 		putleaf( PCC_ICON , text(ap) ? 0: width(ap->type) , 0 , PCCT_INT , (char *) 0 );
1212*18467Sralph 		putop( PCC_CM , PCCT_INT );
1213*18467Sralph 		putop( PCC_CALL , PCCT_INT );
1214766Speter 		putdot( filename , line );
1215766Speter 		return;
1216766Speter 
1217766Speter 	case O_NEW:
1218766Speter 	case O_DISPOSE:
1219766Speter 		if (argc == 0) {
1220766Speter 			error("%s expects at least one argument", p->symbol);
1221766Speter 			return;
1222766Speter 		}
122315934Smckusick 		alv = argv->list_node.list;
12247967Smckusick 		codeoff();
12259139Smckusick 		ap = stklval(alv, op == O_NEW ? ( MOD | NOUSE ) : MOD );
12267967Smckusick 		codeon();
122715934Smckusick 		if (ap == NLNIL)
1228766Speter 			return;
1229766Speter 		if (ap->class != PTR) {
1230766Speter 			error("(First) argument to %s must be a pointer, not %s", p->symbol, nameof(ap));
1231766Speter 			return;
1232766Speter 		}
1233766Speter 		ap = ap->type;
123415934Smckusick 		if (ap == NLNIL)
1235766Speter 			return;
12369139Smckusick 		if (op == O_NEW)
12379139Smckusick 			cmd = "_NEW";
12389139Smckusick 		else /* op == O_DISPOSE */
12397967Smckusick 			if ((ap->nl_flags & NFILES) != 0)
12407967Smckusick 				cmd = "_DFDISPOSE";
12417967Smckusick 			else
12427967Smckusick 				cmd = "_DISPOSE";
1243*18467Sralph 		putleaf( PCC_ICON, 0, 0, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ), cmd);
124415934Smckusick 		(void) stklval(alv, op == O_NEW ? ( MOD | NOUSE ) : MOD );
124515934Smckusick 		argv = argv->list_node.next;
124615934Smckusick 		if (argv != TR_NIL) {
1247766Speter 			if (ap->class != RECORD) {
1248766Speter 				error("Record required when specifying variant tags");
1249766Speter 				return;
1250766Speter 			}
125115934Smckusick 			for (; argv != TR_NIL; argv = argv->list_node.next) {
1252766Speter 				if (ap->ptr[NL_VARNT] == NIL) {
1253766Speter 					error("Too many tag fields");
1254766Speter 					return;
1255766Speter 				}
125615934Smckusick 				if (!isconst(argv->list_node.list)) {
1257766Speter 					error("Second and successive arguments to %s must be constants", p->symbol);
1258766Speter 					return;
1259766Speter 				}
126015934Smckusick 				gconst(argv->list_node.list);
1261766Speter 				if (con.ctype == NIL)
1262766Speter 					return;
126315934Smckusick 				if (incompat(con.ctype, (ap->ptr[NL_TAG])->type , TR_NIL )) {
1264766Speter 					cerror("Specified tag constant type clashed with variant case selector type");
1265766Speter 					return;
1266766Speter 				}
1267766Speter 				for (ap = ap->ptr[NL_VARNT]; ap != NIL; ap = ap->chain)
1268766Speter 					if (ap->range[0] == con.crval)
1269766Speter 						break;
1270766Speter 				if (ap == NIL) {
1271766Speter 					error("No variant case label value equals specified constant value");
1272766Speter 					return;
1273766Speter 				}
1274766Speter 				ap = ap->ptr[NL_VTOREC];
1275766Speter 			}
1276766Speter 		}
1277*18467Sralph 		putleaf( PCC_ICON , width( ap ) , 0 , PCCT_INT , (char *) 0 );
1278*18467Sralph 		putop( PCC_CM , PCCT_INT );
1279*18467Sralph 		putop( PCC_CALL , PCCT_INT );
1280766Speter 		putdot( filename , line );
12819139Smckusick 		if (opt('t') && op == O_NEW) {
1282*18467Sralph 		    putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
12839139Smckusick 			    , "_blkclr" );
128415934Smckusick 		    (void) stkrval(alv, NLNIL , (long) RREQ );
1285*18467Sralph 		    putleaf( PCC_ICON , width( ap ) , 0 , PCCT_INT , (char *) 0 );
1286*18467Sralph 		    putop( PCC_CM , PCCT_INT );
1287*18467Sralph 		    putop( PCC_CALL , PCCT_INT );
12889139Smckusick 		    putdot( filename , line );
12899139Smckusick 		}
1290766Speter 		return;
1291766Speter 
1292766Speter 	case O_DATE:
1293766Speter 	case O_TIME:
1294766Speter 		if (argc != 1) {
1295766Speter 			error("%s expects one argument", p->symbol);
1296766Speter 			return;
1297766Speter 		}
1298*18467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1299766Speter 			, op == O_DATE ? "_DATE" : "_TIME" );
130015934Smckusick 		ap = stklval(argv->list_node.list, MOD|NOUSE);
1301766Speter 		if (ap == NIL)
1302766Speter 			return;
1303766Speter 		if (classify(ap) != TSTR || width(ap) != 10) {
1304766Speter 			error("Argument to %s must be a alfa, not %s", p->symbol, nameof(ap));
1305766Speter 			return;
1306766Speter 		}
1307*18467Sralph 		putop( PCC_CALL , PCCT_INT );
1308766Speter 		putdot( filename , line );
1309766Speter 		return;
1310766Speter 
1311766Speter 	case O_HALT:
1312766Speter 		if (argc != 0) {
1313766Speter 			error("halt takes no arguments");
1314766Speter 			return;
1315766Speter 		}
1316*18467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1317766Speter 			, "_HALT" );
1318766Speter 
1319*18467Sralph 		putop( PCCOM_UNARY PCC_CALL , PCCT_INT );
1320766Speter 		putdot( filename , line );
132115934Smckusick 		noreach = TRUE;
1322766Speter 		return;
1323766Speter 
1324766Speter 	case O_ARGV:
1325766Speter 		if (argc != 2) {
1326766Speter 			error("argv takes two arguments");
1327766Speter 			return;
1328766Speter 		}
1329*18467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1330766Speter 			, "_ARGV" );
133115934Smckusick 		ap = stkrval(argv->list_node.list, NLNIL , (long) RREQ );
133215934Smckusick 		if (ap == NLNIL)
1333766Speter 			return;
1334766Speter 		if (isnta(ap, "i")) {
1335766Speter 			error("argv's first argument must be an integer, not %s", nameof(ap));
1336766Speter 			return;
1337766Speter 		}
133815934Smckusick 		al = argv->list_node.next;
133915934Smckusick 		ap = stklval(al->list_node.list, MOD|NOUSE);
134015934Smckusick 		if (ap == NLNIL)
1341766Speter 			return;
1342766Speter 		if (classify(ap) != TSTR) {
1343766Speter 			error("argv's second argument must be a string, not %s", nameof(ap));
1344766Speter 			return;
1345766Speter 		}
1346*18467Sralph 		putop( PCC_CM , PCCT_INT );
1347*18467Sralph 		putleaf( PCC_ICON , width( ap ) , 0 , PCCT_INT , (char *) 0 );
1348*18467Sralph 		putop( PCC_CM , PCCT_INT );
1349*18467Sralph 		putop( PCC_CALL , PCCT_INT );
1350766Speter 		putdot( filename , line );
1351766Speter 		return;
1352766Speter 
1353766Speter 	case O_STLIM:
1354766Speter 		if (argc != 1) {
1355766Speter 			error("stlimit requires one argument");
1356766Speter 			return;
1357766Speter 		}
1358*18467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1359766Speter 			, "_STLIM" );
136015934Smckusick 		ap = stkrval(argv->list_node.list, NLNIL , (long) RREQ );
136115934Smckusick 		if (ap == NLNIL)
1362766Speter 			return;
1363766Speter 		if (isnta(ap, "i")) {
1364766Speter 			error("stlimit's argument must be an integer, not %s", nameof(ap));
1365766Speter 			return;
1366766Speter 		}
1367*18467Sralph 		putop( PCC_CALL , PCCT_INT );
1368766Speter 		putdot( filename , line );
1369766Speter 		return;
1370766Speter 
1371766Speter 	case O_REMOVE:
1372766Speter 		if (argc != 1) {
1373766Speter 			error("remove expects one argument");
1374766Speter 			return;
1375766Speter 		}
1376*18467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1377766Speter 			, "_REMOVE" );
137815934Smckusick 		ap = stkrval(argv->list_node.list, NLNIL, (long) RREQ );
137915934Smckusick 		if (ap == NLNIL)
1380766Speter 			return;
1381766Speter 		if (classify(ap) != TSTR) {
1382766Speter 			error("remove's argument must be a string, not %s", nameof(ap));
1383766Speter 			return;
1384766Speter 		}
1385*18467Sralph 		putleaf( PCC_ICON , width( ap ) , 0 , PCCT_INT , (char *) 0 );
1386*18467Sralph 		putop( PCC_CM , PCCT_INT );
1387*18467Sralph 		putop( PCC_CALL , PCCT_INT );
1388766Speter 		putdot( filename , line );
1389766Speter 		return;
1390766Speter 
1391766Speter 	case O_LLIMIT:
1392766Speter 		if (argc != 2) {
1393766Speter 			error("linelimit expects two arguments");
1394766Speter 			return;
1395766Speter 		}
1396*18467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1397766Speter 			, "_LLIMIT" );
139815934Smckusick 		ap = stklval(argv->list_node.list, NOFLAGS|NOUSE);
139915934Smckusick 		if (ap == NLNIL)
1400766Speter 			return;
1401766Speter 		if (!text(ap)) {
1402766Speter 			error("linelimit's first argument must be a text file, not %s", nameof(ap));
1403766Speter 			return;
1404766Speter 		}
140515934Smckusick 		al = argv->list_node.next;
140615934Smckusick 		ap = stkrval(al->list_node.list, NLNIL , (long) RREQ );
140715934Smckusick 		if (ap == NLNIL)
1408766Speter 			return;
1409766Speter 		if (isnta(ap, "i")) {
1410766Speter 			error("linelimit's second argument must be an integer, not %s", nameof(ap));
1411766Speter 			return;
1412766Speter 		}
1413*18467Sralph 		putop( PCC_CM , PCCT_INT );
1414*18467Sralph 		putop( PCC_CALL , PCCT_INT );
1415766Speter 		putdot( filename , line );
1416766Speter 		return;
1417766Speter 	case O_PAGE:
1418766Speter 		if (argc != 1) {
1419766Speter 			error("page expects one argument");
1420766Speter 			return;
1421766Speter 		}
1422*18467Sralph 		putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
1423*18467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1424766Speter 			, "_UNIT" );
142515934Smckusick 		ap = stklval(argv->list_node.list, NOFLAGS);
142615934Smckusick 		if (ap == NLNIL)
1427766Speter 			return;
1428766Speter 		if (!text(ap)) {
1429766Speter 			error("Argument to page must be a text file, not %s", nameof(ap));
1430766Speter 			return;
1431766Speter 		}
1432*18467Sralph 		putop( PCC_CALL , PCCT_INT );
1433*18467Sralph 		putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY );
1434766Speter 		putdot( filename , line );
1435766Speter 		if ( opt( 't' ) ) {
1436*18467Sralph 		    putleaf( PCC_ICON , 0 , 0
1437*18467Sralph 			, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1438766Speter 			, "_PAGE" );
1439*18467Sralph 		    putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
1440766Speter 		} else {
1441*18467Sralph 		    putleaf( PCC_ICON , 0 , 0
1442*18467Sralph 			, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1443766Speter 			, "_fputc" );
1444*18467Sralph 		    putleaf( PCC_ICON , '\f' , 0 , (int) PCCT_CHAR , (char *) 0 );
1445*18467Sralph 		    putleaf( PCC_ICON , 0 , 0
1446*18467Sralph 			, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1447766Speter 			, "_ACTFILE" );
1448*18467Sralph 		    putRV((char *) 0 , cbn , CURFILEOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
1449*18467Sralph 		    putop( PCC_CALL , PCCT_INT );
1450*18467Sralph 		    putop( PCC_CM , PCCT_INT );
1451766Speter 		}
1452*18467Sralph 		putop( PCC_CALL , PCCT_INT );
1453766Speter 		putdot( filename , line );
1454766Speter 		return;
1455766Speter 
14567928Smckusick 	case O_ASRT:
14577928Smckusick 		if (!opt('t'))
14587928Smckusick 			return;
14597928Smckusick 		if (argc == 0 || argc > 2) {
14607928Smckusick 			error("Assert expects one or two arguments");
14617928Smckusick 			return;
14627928Smckusick 		}
14639139Smckusick 		if (argc == 2)
14649139Smckusick 			cmd = "_ASRTS";
14659139Smckusick 		else
14669139Smckusick 			cmd = "_ASRT";
1467*18467Sralph 		putleaf( PCC_ICON , 0 , 0
1468*18467Sralph 		    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , cmd );
146915934Smckusick 		ap = stkrval(argv->list_node.list, NLNIL , (long) RREQ );
147015934Smckusick 		if (ap == NLNIL)
14717928Smckusick 			return;
14727928Smckusick 		if (isnta(ap, "b"))
14737928Smckusick 			error("Assert expression must be Boolean, not %ss", nameof(ap));
14747928Smckusick 		if (argc == 2) {
14757928Smckusick 			/*
14767928Smckusick 			 * Optional second argument is a string specifying
14777928Smckusick 			 * why the assertion failed.
14787928Smckusick 			 */
147915934Smckusick 			al = argv->list_node.next;
148015934Smckusick 			al = (struct tnode *) stkrval(al->list_node.list, NLNIL , (long) RREQ );
148115934Smckusick 			if (al == TR_NIL)
14827928Smckusick 				return;
148315934Smckusick 			if (classify((struct nl *) al) != TSTR) {
148415934Smckusick 				error("Second argument to assert must be a string, not %s", nameof((struct nl *) al));
14857928Smckusick 				return;
14867928Smckusick 			}
1487*18467Sralph 			putop( PCC_CM , PCCT_INT );
14887928Smckusick 		}
1489*18467Sralph 		putop( PCC_CALL , PCCT_INT );
14907928Smckusick 		putdot( filename , line );
14917928Smckusick 		return;
14927928Smckusick 
1493766Speter 	case O_PACK:
1494766Speter 		if (argc != 3) {
1495766Speter 			error("pack expects three arguments");
1496766Speter 			return;
1497766Speter 		}
1498*18467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1499766Speter 			, "_PACK" );
1500766Speter 		pu = "pack(a,i,z)";
150115934Smckusick 		pua = (al = argv)->list_node.list;
150215934Smckusick 		pui = (al = al->list_node.next)->list_node.list;
150315934Smckusick 		puz = (al = al->list_node.next)->list_node.list;
1504766Speter 		goto packunp;
1505766Speter 	case O_UNPACK:
1506766Speter 		if (argc != 3) {
1507766Speter 			error("unpack expects three arguments");
1508766Speter 			return;
1509766Speter 		}
1510*18467Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1511766Speter 			, "_UNPACK" );
1512766Speter 		pu = "unpack(z,a,i)";
151315934Smckusick 		puz = (al = argv)->list_node.list;
151415934Smckusick 		pua = (al = al->list_node.next)->list_node.list;
151515934Smckusick 		pui = (al = al->list_node.next)->list_node.list;
1516766Speter packunp:
151715934Smckusick 		ap = stkrval(pui, NLNIL , (long) RREQ );
1518766Speter 		if (ap == NIL)
1519766Speter 			return;
1520766Speter 		ap = stklval(pua, op == O_PACK ? NOFLAGS : MOD|NOUSE);
1521766Speter 		if (ap == NIL)
1522766Speter 			return;
1523766Speter 		if (ap->class != ARRAY) {
1524766Speter 			error("%s requires a to be an unpacked array, not %s", pu, nameof(ap));
1525766Speter 			return;
1526766Speter 		}
1527*18467Sralph 		putop( PCC_CM , PCCT_INT );
152815934Smckusick 		al = (struct tnode *) stklval(puz, op == O_UNPACK ? NOFLAGS : MOD|NOUSE);
152915934Smckusick 		if (((struct nl *) al)->class != ARRAY) {
1530766Speter 			error("%s requires z to be a packed array, not %s", pu, nameof(ap));
1531766Speter 			return;
1532766Speter 		}
153315934Smckusick 		if (((struct nl *) al)->type == NIL ||
153415934Smckusick 			((struct nl *) ap)->type == NIL)
1535766Speter 			return;
153615934Smckusick 		if (((struct nl *) al)->type != ((struct nl *) ap)->type) {
1537766Speter 			error("%s requires a and z to be arrays of the same type", pu, nameof(ap));
1538766Speter 			return;
1539766Speter 		}
1540*18467Sralph 		putop( PCC_CM , PCCT_INT );
154115934Smckusick 		k = width((struct nl *) al);
1542766Speter 		itemwidth = width(ap->type);
1543766Speter 		ap = ap->chain;
154415934Smckusick 		al = ((struct tnode *) ((struct nl *) al)->chain);
154515934Smckusick 		if (ap->chain != NIL || ((struct nl *) al)->chain != NIL) {
1546766Speter 			error("%s requires a and z to be single dimension arrays", pu);
1547766Speter 			return;
1548766Speter 		}
1549766Speter 		if (ap == NIL || al == NIL)
1550766Speter 			return;
1551766Speter 		/*
1552766Speter 		 * al is the range for z i.e. u..v
1553766Speter 		 * ap is the range for a i.e. m..n
1554766Speter 		 * i will be n-m+1
1555766Speter 		 * j will be v-u+1
1556766Speter 		 */
1557766Speter 		i = ap->range[1] - ap->range[0] + 1;
155815934Smckusick 		j = ((struct nl *) al)->range[1] -
155915934Smckusick 			((struct nl *) al)->range[0] + 1;
1560766Speter 		if (i < j) {
156115934Smckusick 			error("%s cannot have more elements in a (%d) than in z (%d)", pu, (char *) j, (char *) i);
1562766Speter 			return;
1563766Speter 		}
1564766Speter 		/*
1565766Speter 		 * get n-m-(v-u) and m for the interpreter
1566766Speter 		 */
1567766Speter 		i -= j;
1568766Speter 		j = ap->range[0];
1569*18467Sralph 		putleaf( PCC_ICON , itemwidth , 0 , PCCT_INT , (char *) 0 );
1570*18467Sralph 		putop( PCC_CM , PCCT_INT );
1571*18467Sralph 		putleaf( PCC_ICON , j , 0 , PCCT_INT , (char *) 0 );
1572*18467Sralph 		putop( PCC_CM , PCCT_INT );
1573*18467Sralph 		putleaf( PCC_ICON , i , 0 , PCCT_INT , (char *) 0 );
1574*18467Sralph 		putop( PCC_CM , PCCT_INT );
1575*18467Sralph 		putleaf( PCC_ICON , k , 0 , PCCT_INT , (char *) 0 );
1576*18467Sralph 		putop( PCC_CM , PCCT_INT );
1577*18467Sralph 		putop( PCC_CALL , PCCT_INT );
1578766Speter 		putdot( filename , line );
1579766Speter 		return;
1580766Speter 	case 0:
15817928Smckusick 		error("%s is an unimplemented extension", p->symbol);
1582766Speter 		return;
1583766Speter 
1584766Speter 	default:
1585766Speter 		panic("proc case");
1586766Speter 	}
1587766Speter }
1588766Speter #endif PC
1589