Implement formal functions and procedures
[unix-history] / usr / src / usr.bin / pascal / src / pcproc.c
CommitLineData
076fd8d4
PK
1/* Copyright (c) 1979 Regents of the University of California */
2
c4e911b6 3static char sccsid[] = "@(#)pcproc.c 1.2 %G%";
076fd8d4
PK
4
5#include "whoami.h"
6#ifdef PC
7 /*
8 * and to the end of the file
9 */
10#include "0.h"
11#include "tree.h"
12#include "opcode.h"
13#include "pc.h"
14#include "pcops.h"
15
16/*
17 * The following array is used to determine which classes may be read
18 * from textfiles. It is indexed by the return value from classify.
19 */
20#define rdops(x) rdxxxx[(x)-(TFIRST)]
21
22int rdxxxx[] = {
23 0, /* -7 file types */
24 0, /* -6 record types */
25 0, /* -5 array types */
26 O_READE, /* -4 scalar types */
27 0, /* -3 pointer types */
28 0, /* -2 set types */
29 0, /* -1 string types */
30 0, /* 0 nil, no type */
31 O_READE, /* 1 boolean */
32 O_READC, /* 2 character */
33 O_READ4, /* 3 integer */
34 O_READ8 /* 4 real */
35};
36\f
37/*
38 * Proc handles procedure calls.
39 * Non-builtin procedures are "buck-passed" to func (with a flag
40 * indicating that they are actually procedures.
41 * builtin procedures are handled here.
42 */
43pcproc(r)
44 int *r;
45{
46 register struct nl *p;
47 register int *alv, *al, op;
48 struct nl *filetype, *ap;
49 int argc, *argv, typ, fmtspec, strfmt, stkcnt, *file;
50 char fmt, format[20], *strptr;
51 int prec, field, strnglen, fmtlen, fmtstart, pu;
52 int *pua, *pui, *puz;
53 int i, j, k;
54 int itemwidth;
55 char *readname;
56 long tempoff;
57 long readtype;
58
59#define CONPREC 4
60#define VARPREC 8
61#define CONWIDTH 1
62#define VARWIDTH 2
63#define SKIP 16
64
65 /*
66 * Verify that the name is
67 * defined and is that of a
68 * procedure.
69 */
70 p = lookup(r[2]);
71 if (p == NIL) {
72 rvlist(r[3]);
73 return;
74 }
c4e911b6 75 if (p->class != PROC && p->class != FPROC) {
076fd8d4
PK
76 error("Can't call %s, its %s not a procedure", p->symbol, classes[p->class]);
77 rvlist(r[3]);
78 return;
79 }
80 argv = r[3];
81
82 /*
83 * Call handles user defined
84 * procedures and functions.
85 */
86 if (bn != 0) {
87 call(p, argv, PROC, bn);
88 return;
89 }
90
91 /*
92 * Call to built-in procedure.
93 * Count the arguments.
94 */
95 argc = 0;
96 for (al = argv; al != NIL; al = al[2])
97 argc++;
98
99 /*
100 * Switch on the operator
101 * associated with the built-in
102 * procedure in the namelist
103 */
104 op = p->value[0] &~ NSTAND;
105 if (opt('s') && (p->value[0] & NSTAND)) {
106 standard();
107 error("%s is a nonstandard procedure", p->symbol);
108 }
109 switch (op) {
110
111 case O_ABORT:
112 if (argc != 0)
113 error("null takes no arguments");
114 return;
115
116 case O_FLUSH:
117 if (argc == 0) {
118 putleaf( P2ICON , 0 , 0 , P2INT , "_PFLUSH" );
119 putop( P2UNARY P2CALL , P2INT );
120 putdot( filename , line );
121 return;
122 }
123 if (argc != 1) {
124 error("flush takes at most one argument");
125 return;
126 }
127 putleaf( P2ICON , 0 , 0
128 , ADDTYPE( P2FTN | P2INT , P2PTR )
129 , "_FLUSH" );
130 ap = stklval(argv[1], NOFLAGS);
131 if (ap == NIL)
132 return;
133 if (ap->class != FILET) {
134 error("flush's argument must be a file, not %s", nameof(ap));
135 return;
136 }
137 putop( P2CALL , P2INT );
138 putdot( filename , line );
139 return;
140
141 case O_MESSAGE:
142 case O_WRITEF:
143 case O_WRITLN:
144 /*
145 * Set up default file "output"'s type
146 */
147 file = NIL;
148 filetype = nl+T1CHAR;
149 /*
150 * Determine the file implied
151 * for the write and generate
152 * code to make it the active file.
153 */
154 if (op == O_MESSAGE) {
155 /*
156 * For message, all that matters
157 * is that the filetype is
158 * a character file.
159 * Thus "output" will suit us fine.
160 */
161 putleaf( P2ICON , 0 , 0 , P2INT , "_PFLUSH" );
162 putop( P2UNARY P2CALL , P2INT );
163 putdot( filename , line );
164 putRV( 0 , cbn , CURFILEOFFSET , P2PTR|P2STRTY );
165 putLV( "__err" , 0 , 0 , P2PTR|P2STRTY );
166 putop( P2ASSIGN , P2PTR|P2STRTY );
167 putdot( filename , line );
168 } else if (argv != NIL && (al = argv[1])[0] != T_WEXP) {
169 /*
170 * If there is a first argument which has
171 * no write widths, then it is potentially
172 * a file name.
173 */
174 codeoff();
175 ap = stkrval(argv[1], NIL , RREQ );
176 codeon();
177 if (ap == NIL)
178 argv = argv[2];
179 if (ap != NIL && ap->class == FILET) {
180 /*
181 * Got "write(f, ...", make
182 * f the active file, and save
183 * it and its type for use in
184 * processing the rest of the
185 * arguments to write.
186 */
187 putRV( 0 , cbn , CURFILEOFFSET
188 , P2PTR|P2STRTY );
189 putleaf( P2ICON , 0 , 0
190 , ADDTYPE( P2FTN | P2INT , P2PTR )
191 , "_UNIT" );
192 file = argv[1];
193 filetype = ap->type;
194 stklval(argv[1], NOFLAGS);
195 putop( P2CALL , P2INT );
196 putop( P2ASSIGN , P2PTR|P2STRTY );
197 putdot( filename , line );
198 /*
199 * Skip over the first argument
200 */
201 argv = argv[2];
202 argc--;
203 } else {
204 /*
205 * Set up for writing on
206 * standard output.
207 */
208 putRV( 0, cbn , CURFILEOFFSET , P2PTR|P2STRTY );
209 putLV( "_output" , 0 , 0 , P2PTR|P2STRTY );
210 putop( P2ASSIGN , P2PTR|P2STRTY );
211 putdot( filename , line );
212 }
213 } else {
214 putRV( 0, cbn , CURFILEOFFSET , P2PTR|P2STRTY );
215 putLV( "_output" , 0 , 0 , P2PTR|P2STRTY );
216 putop( P2ASSIGN , P2PTR|P2STRTY );
217 putdot( filename , line );
218 }
219 /*
220 * Loop and process each
221 * of the arguments.
222 */
223 for (; argv != NIL; argv = argv[2]) {
224 /*
225 * fmtspec indicates the type (CONstant or VARiable)
226 * and number (none, WIDTH, and/or PRECision)
227 * of the fields in the printf format for this
228 * output variable.
229 * stkcnt is the number of longs pushed on the stack
230 * fmt is the format output indicator (D, E, F, O, X, S)
231 * fmtstart = 0 for leading blank; = 1 for no blank
232 */
233 fmtspec = NIL;
234 stkcnt = 0;
235 fmt = 'D';
236 fmtstart = 1;
237 al = argv[1];
238 if (al == NIL)
239 continue;
240 if (al[0] == T_WEXP)
241 alv = al[1];
242 else
243 alv = al;
244 if (alv == NIL)
245 continue;
246 codeoff();
247 ap = stkrval(alv, NIL , RREQ );
248 codeon();
249 if (ap == NIL)
250 continue;
251 typ = classify(ap);
252 if (al[0] == T_WEXP) {
253 /*
254 * Handle width expressions.
255 * The basic game here is that width
256 * expressions get evaluated. If they
257 * are constant, the value is placed
258 * directly in the format string.
259 * Otherwise the value is pushed onto
260 * the stack and an indirection is
261 * put into the format string.
262 */
263 if (al[3] == OCT)
264 fmt = 'O';
265 else if (al[3] == HEX)
266 fmt = 'X';
267 else if (al[3] != NIL) {
268 /*
269 * Evaluate second format spec
270 */
271 if ( constval(al[3])
272 && isa( con.ctype , "i" ) ) {
273 fmtspec += CONPREC;
274 prec = con.crval;
275 } else {
276 fmtspec += VARPREC;
277 }
278 fmt = 'f';
279 switch ( typ ) {
280 case TINT:
281 if ( opt( 's' ) ) {
282 standard();
283 error("Writing %ss with two write widths is non-standard", clnames[typ]);
284 }
285 /* and fall through */
286 case TDOUBLE:
287 break;
288 default:
289 error("Cannot write %ss with two write widths", clnames[typ]);
290 continue;
291 }
292 }
293 /*
294 * Evaluate first format spec
295 */
296 if (al[2] != NIL) {
297 if ( constval(al[2])
298 && isa( con.ctype , "i" ) ) {
299 fmtspec += CONWIDTH;
300 field = con.crval;
301 } else {
302 fmtspec += VARWIDTH;
303 }
304 }
305 if ((fmtspec & CONPREC) && prec < 0 ||
306 (fmtspec & CONWIDTH) && field < 0) {
307 error("Negative widths are not allowed");
308 continue;
309 }
310 }
311 if (filetype != nl+T1CHAR) {
312 if (fmt == 'O' || fmt == 'X') {
313 error("Oct/hex allowed only on text files");
314 continue;
315 }
316 if (fmtspec) {
317 error("Write widths allowed only on text files");
318 continue;
319 }
320 /*
321 * Generalized write, i.e.
322 * to a non-textfile.
323 */
324 putleaf( P2ICON , 0 , 0
325 , ADDTYPE(
326 ADDTYPE(
327 ADDTYPE( p2type( filetype )
328 , P2PTR )
329 , P2FTN )
330 , P2PTR )
331 , "_FNIL" );
332 stklval(file, NOFLAGS);
333 putop( P2CALL
334 , ADDTYPE( p2type( filetype ) , P2PTR ) );
335 putop( P2UNARY P2MUL , p2type( filetype ) );
336 /*
337 * file^ := ...
338 */
339 switch ( classify( filetype ) ) {
340 case TBOOL:
341 case TCHAR:
342 case TINT:
343 case TSCAL:
344 precheck( filetype , "_RANG4" , "_RSGN4" );
345 /* and fall through */
346 case TDOUBLE:
347 case TPTR:
348 ap = rvalue( argv[1] , filetype , RREQ );
349 break;
350 default:
351 ap = rvalue( argv[1] , filetype , LREQ );
352 break;
353 }
354 if (ap == NIL)
355 continue;
356 if (incompat(ap, filetype, argv[1])) {
357 cerror("Type mismatch in write to non-text file");
358 continue;
359 }
360 switch ( classify( filetype ) ) {
361 case TBOOL:
362 case TCHAR:
363 case TINT:
364 case TSCAL:
365 postcheck( filetype );
366 /* and fall through */
367 case TDOUBLE:
368 case TPTR:
369 putop( P2ASSIGN , p2type( filetype ) );
370 putdot( filename , line );
371 break;
372 default:
373 putstrop( P2STASG
374 , p2type( filetype )
375 , lwidth( filetype )
376 , align( filetype ) );
377 putdot( filename , line );
378 break;
379 }
380 /*
381 * put(file)
382 */
383 putleaf( P2ICON , 0 , 0
384 , ADDTYPE( P2FTN | P2INT , P2PTR )
385 , "_PUT" );
386 putRV( 0 , cbn , CURFILEOFFSET
387 , P2PTR|P2STRTY );
388 putop( P2CALL , P2INT );
389 putdot( filename , line );
390 continue;
391 }
392 /*
393 * Write to a textfile
394 *
395 * Evaluate the expression
396 * to be written.
397 */
398 if (fmt == 'O' || fmt == 'X') {
399 if (opt('s')) {
400 standard();
401 error("Oct and hex are non-standard");
402 }
403 if (typ == TSTR || typ == TDOUBLE) {
404 error("Can't write %ss with oct/hex", clnames[typ]);
405 continue;
406 }
407 if (typ == TCHAR || typ == TBOOL)
408 typ = TINT;
409 }
410 /*
411 * If there is no format specified by the programmer,
412 * implement the default.
413 */
414 switch (typ) {
415 case TINT:
416 if (fmt == 'f') {
417 typ = TDOUBLE;
418 goto tdouble;
419 }
420 if (fmtspec == NIL) {
421 if (fmt == 'D')
422 field = 10;
423 else if (fmt == 'X')
424 field = 8;
425 else if (fmt == 'O')
426 field = 11;
427 else
428 panic("fmt1");
429 fmtspec = CONWIDTH;
430 }
431 break;
432 case TCHAR:
433 tchar:
434 fmt = 'c';
435 break;
436 case TSCAL:
437 if (opt('s')) {
438 standard();
439 error("Writing scalars to text files is non-standard");
440 }
441 case TBOOL:
442 fmt = 's';
443 break;
444 case TDOUBLE:
445 tdouble:
446 switch (fmtspec) {
447 case NIL:
448 field = 21;
449 prec = 14;
450 fmt = 'E';
451 fmtspec = CONWIDTH + CONPREC;
452 break;
453 case CONWIDTH:
454 if (--field < 1)
455 field = 1;
456 prec = field - 7;
457 if (prec < 1)
458 prec = 1;
459 fmtspec += CONPREC;
460 fmt = 'E';
461 break;
462 case VARWIDTH:
463 fmtspec += VARPREC;
464 fmt = 'E';
465 break;
466 case CONWIDTH + CONPREC:
467 case CONWIDTH + VARPREC:
468 if (--field < 1)
469 field = 1;
470 }
471 format[0] = ' ';
472 fmtstart = 0;
473 break;
474 case TSTR:
475 constval( alv );
476 switch ( classify( con.ctype ) ) {
477 case TCHAR:
478 typ = TCHAR;
479 goto tchar;
480 case TSTR:
481 strptr = con.cpval;
482 for (strnglen = 0; *strptr++; strnglen++) /* void */;
483 strptr = con.cpval;
484 break;
485 default:
486 strnglen = width(ap);
487 break;
488 }
489 fmt = 's';
490 strfmt = fmtspec;
491 if (fmtspec == NIL) {
492 fmtspec = SKIP;
493 break;
494 }
495 if (fmtspec & CONWIDTH) {
496 if (field <= strnglen)
497 fmtspec = SKIP;
498 else
499 field -= strnglen;
500 }
501 break;
502 default:
503 error("Can't write %ss to a text file", clnames[typ]);
504 continue;
505 }
506 /*
507 * Generate the format string
508 */
509 switch (fmtspec) {
510 default:
511 panic("fmt2");
512 case NIL:
513 if (fmt == 'c') {
514 if ( opt( 't' ) ) {
515 putleaf( P2ICON , 0 , 0
516 , ADDTYPE( P2FTN|P2INT , P2PTR )
517 , "_WRITEC" );
518 putRV( 0 , cbn , CURFILEOFFSET
519 , P2PTR|P2STRTY );
520 stkrval( alv , NIL , RREQ );
521 putop( P2LISTOP , P2INT );
522 } else {
523 putleaf( P2ICON , 0 , 0
524 , ADDTYPE( P2FTN|P2INT , P2PTR )
525 , "_fputc" );
526 stkrval( alv , NIL , RREQ );
527 }
528 putleaf( P2ICON , 0 , 0
529 , ADDTYPE( P2FTN | P2INT , P2PTR )
530 , "_ACTFILE" );
531 putRV( 0, cbn , CURFILEOFFSET
532 , P2PTR|P2STRTY );
533 putop( P2CALL , P2INT );
534 putop( P2LISTOP , P2INT );
535 putop( P2CALL , P2INT );
536 putdot( filename , line );
537 } else {
538 sprintf(&format[1], "%%%c", fmt);
539 goto fmtgen;
540 }
541 case SKIP:
542 break;
543 case CONWIDTH:
544 sprintf(&format[1], "%%%1D%c", field, fmt);
545 goto fmtgen;
546 case VARWIDTH:
547 sprintf(&format[1], "%%*%c", fmt);
548 goto fmtgen;
549 case CONWIDTH + CONPREC:
550 sprintf(&format[1], "%%%1D.%1D%c", field, prec, fmt);
551 goto fmtgen;
552 case CONWIDTH + VARPREC:
553 sprintf(&format[1], "%%%1D.*%c", field, fmt);
554 goto fmtgen;
555 case VARWIDTH + CONPREC:
556 sprintf(&format[1], "%%*.%1D%c", prec, fmt);
557 goto fmtgen;
558 case VARWIDTH + VARPREC:
559 sprintf(&format[1], "%%*.*%c", fmt);
560 fmtgen:
561 if ( opt( 't' ) ) {
562 putleaf( P2ICON , 0 , 0
563 , ADDTYPE( P2FTN | P2INT , P2PTR )
564 , "_WRITEF" );
565 putRV( 0 , cbn , CURFILEOFFSET
566 , P2PTR|P2STRTY );
567 putleaf( P2ICON , 0 , 0
568 , ADDTYPE( P2FTN | P2INT , P2PTR )
569 , "_ACTFILE" );
570 putRV( 0 , cbn , CURFILEOFFSET
571 , P2PTR|P2STRTY );
572 putop( P2CALL , P2INT );
573 putop( P2LISTOP , P2INT );
574 } else {
575 putleaf( P2ICON , 0 , 0
576 , ADDTYPE( P2FTN | P2INT , P2PTR )
577 , "_fprintf" );
578 putleaf( P2ICON , 0 , 0
579 , ADDTYPE( P2FTN | P2INT , P2PTR )
580 , "_ACTFILE" );
581 putRV( 0 , cbn , CURFILEOFFSET
582 , P2PTR|P2STRTY );
583 putop( P2CALL , P2INT );
584 }
585 putCONG( &format[ fmtstart ]
586 , strlen( &format[ fmtstart ] )
587 , LREQ );
588 putop( P2LISTOP , P2INT );
589 if ( fmtspec & VARWIDTH ) {
590 /*
591 * either
592 * ,(temp=width,MAX(temp,...)),
593 * or
594 * , MAX( width , ... ) ,
595 */
596 if ( ( typ == TDOUBLE && al[3] == NIL )
597 || typ == TSTR ) {
598 sizes[ cbn ].om_off -= sizeof( int );
599 tempoff = sizes[ cbn ].om_off;
600 putlbracket( ftnno , -tempoff );
601 if ( tempoff < sizes[ cbn ].om_max ) {
602 sizes[ cbn ].om_max = tempoff;
603 }
604 putRV( 0 , cbn , tempoff , P2INT );
605 ap = stkrval( al[2] , NIL , RREQ );
606 putop( P2ASSIGN , P2INT );
607 putleaf( P2ICON , 0 , 0
608 , ADDTYPE( P2FTN | P2INT , P2PTR )
609 , "_MAX" );
610 putRV( 0 , cbn , tempoff , P2INT );
611 } else {
612 if (opt('t')
613 || typ == TSTR || typ == TDOUBLE) {
614 putleaf( P2ICON , 0 , 0
615 ,ADDTYPE( P2FTN | P2INT, P2PTR )
616 ,"_MAX" );
617 }
618 ap = stkrval( al[2] , NIL , RREQ );
619 }
620 if (ap == NIL)
621 continue;
622 if (isnta(ap,"i")) {
623 error("First write width must be integer, not %s", nameof(ap));
624 continue;
625 }
626 switch ( typ ) {
627 case TDOUBLE:
628 putleaf( P2ICON , 1 , 0 , P2INT , 0 );
629 putop( P2LISTOP , P2INT );
630 putleaf( P2ICON , 1 , 0 , P2INT , 0 );
631 putop( P2LISTOP , P2INT );
632 putop( P2CALL , P2INT );
633 if ( al[3] == NIL ) {
634 /*
635 * finish up the comma op
636 */
637 putop( P2COMOP , P2INT );
638 fmtspec &= ~VARPREC;
639 putop( P2LISTOP , P2INT );
640 putleaf( P2ICON , 0 , 0
641 , ADDTYPE( P2FTN | P2INT , P2PTR )
642 , "_MAX" );
643 putRV( 0 , cbn , tempoff , P2INT );
644 sizes[ cbn ].om_off += sizeof( int );
645 putleaf( P2ICON , 8 , 0 , P2INT , 0 );
646 putop( P2LISTOP , P2INT );
647 putleaf( P2ICON , 1 , 0 , P2INT , 0 );
648 putop( P2LISTOP , P2INT );
649 putop( P2CALL , P2INT );
650 }
651 putop( P2LISTOP , P2INT );
652 break;
653 case TSTR:
654 putleaf( P2ICON , strnglen , 0 , P2INT , 0 );
655 putop( P2LISTOP , P2INT );
656 putleaf( P2ICON , 0 , 0 , P2INT , 0 );
657 putop( P2LISTOP , P2INT );
658 putop( P2CALL , P2INT );
659 putop( P2COMOP , P2INT );
660 putop( P2LISTOP , P2INT );
661 break;
662 default:
663 if (opt('t')) {
664 putleaf( P2ICON , 0 , 0 , P2INT , 0 );
665 putop( P2LISTOP , P2INT );
666 putleaf( P2ICON , 0 , 0 , P2INT , 0 );
667 putop( P2LISTOP , P2INT );
668 putop( P2CALL , P2INT );
669 }
670 putop( P2LISTOP , P2INT );
671 break;
672 }
673 }
674 /*
675 * If there is a variable precision,
676 * evaluate it
677 */
678 if (fmtspec & VARPREC) {
679 if (opt('t')) {
680 putleaf( P2ICON , 0 , 0
681 , ADDTYPE( P2FTN | P2INT , P2PTR )
682 , "_MAX" );
683 }
684 ap = stkrval( al[3] , NIL , RREQ );
685 if (ap == NIL)
686 continue;
687 if (isnta(ap,"i")) {
688 error("Second write width must be integer, not %s", nameof(ap));
689 continue;
690 }
691 if (opt('t')) {
692 putleaf( P2ICON , 0 , 0 , P2INT , 0 );
693 putop( P2LISTOP , P2INT );
694 putleaf( P2ICON , 0 , 0 , P2INT , 0 );
695 putop( P2LISTOP , P2INT );
696 putop( P2CALL , P2INT );
697 }
698 putop( P2LISTOP , P2INT );
699 }
700 /*
701 * evaluate the thing we want printed.
702 */
703 switch ( typ ) {
704 case TCHAR:
705 case TINT:
706 stkrval( alv , NIL , RREQ );
707 putop( P2LISTOP , P2INT );
708 break;
709 case TDOUBLE:
710 ap = stkrval( alv , NIL , RREQ );
711 if ( isnta( ap , "d" ) ) {
712 putop( P2SCONV , P2DOUBLE );
713 }
714 putop( P2LISTOP , P2INT );
715 break;
716 case TSCAL:
717 case TBOOL:
718 putleaf( P2ICON , 0 , 0
719 , ADDTYPE( P2FTN | P2INT , P2PTR )
720 , "_NAM" );
721 ap = stkrval( alv , NIL , RREQ );
722 sprintf( format , PREFIXFORMAT , LABELPREFIX
723 , listnames( ap ) );
724 putleaf( P2ICON , 0 , 0 , P2PTR | P2CHAR
725 , format );
726 putop( P2LISTOP , P2INT );
727 putop( P2CALL , P2INT );
728 putop( P2LISTOP , P2INT );
729 break;
730 case TSTR:
731 putCONG( "" , 0 , LREQ );
732 putop( P2LISTOP , P2INT );
733 break;
734 }
735 putop( P2CALL , P2INT );
736 putdot( filename , line );
737 }
738 /*
739 * Write the string after its blank padding
740 */
741 if (typ == TSTR ) {
742 if ( opt( 't' ) ) {
743 putleaf( P2ICON , 0 , 0
744 , ADDTYPE( P2FTN | P2INT , P2PTR )
745 , "_WRITES" );
746 putRV( 0 , cbn , CURFILEOFFSET
747 , P2PTR|P2STRTY );
748 ap = stkrval(alv, NIL , RREQ );
749 putop( P2LISTOP , P2INT );
750 } else {
751 putleaf( P2ICON , 0 , 0
752 , ADDTYPE( P2FTN | P2INT , P2PTR )
753 , "_fwrite" );
754 ap = stkrval(alv, NIL , RREQ );
755 }
756 if (strfmt & VARWIDTH) {
757 /*
758 * min, inline expanded as
759 * temp < len ? temp : len
760 */
761 putRV( 0 , cbn , tempoff , P2INT );
762 putleaf( P2ICON , strnglen , 0 , P2INT , 0 );
763 putop( P2LT , P2INT );
764 putRV( 0 , cbn , tempoff , P2INT );
765 putleaf( P2ICON , strnglen , 0 , P2INT , 0 );
766 putop( P2COLON , P2INT );
767 putop( P2QUEST , P2INT );
768 } else {
769 if ( ( fmtspec & SKIP )
770 && ( strfmt & CONWIDTH ) ) {
771 strnglen = field;
772 }
773 putleaf( P2ICON , strnglen , 0 , P2INT , 0 );
774 }
775 putop( P2LISTOP , P2INT );
776 putleaf( P2ICON , 1 , 0 , P2INT , 0 );
777 putop( P2LISTOP , P2INT );
778 putleaf( P2ICON , 0 , 0
779 , ADDTYPE( P2FTN | P2INT , P2PTR )
780 , "_ACTFILE" );
781 putRV( 0, cbn , CURFILEOFFSET , P2PTR|P2STRTY );
782 putop( P2CALL , P2INT );
783 putop( P2LISTOP , P2INT );
784 putop( P2CALL , P2INT );
785 putdot( filename , line );
786 }
787 }
788 /*
789 * Done with arguments.
790 * Handle writeln and
791 * insufficent number of args.
792 */
793 switch (p->value[0] &~ NSTAND) {
794 case O_WRITEF:
795 if (argc == 0)
796 error("Write requires an argument");
797 break;
798 case O_MESSAGE:
799 if (argc == 0)
800 error("Message requires an argument");
801 case O_WRITLN:
802 if (filetype != nl+T1CHAR)
803 error("Can't 'writeln' a non text file");
804 if ( opt( 't' ) ) {
805 putleaf( P2ICON , 0 , 0
806 , ADDTYPE( P2FTN | P2INT , P2PTR )
807 , "_WRITLN" );
808 putRV( 0 , cbn , CURFILEOFFSET
809 , P2PTR|P2STRTY );
810 } else {
811 putleaf( P2ICON , 0 , 0
812 , ADDTYPE( P2FTN | P2INT , P2PTR )
813 , "_fputc" );
814 putleaf( P2ICON , '\n' , 0 , P2CHAR , 0 );
815 putleaf( P2ICON , 0 , 0
816 , ADDTYPE( P2FTN | P2INT , P2PTR )
817 , "_ACTFILE" );
818 putRV( 0 , cbn , CURFILEOFFSET
819 , P2PTR|P2STRTY );
820 putop( P2CALL , P2INT );
821 putop( P2LISTOP , P2INT );
822 }
823 putop( P2CALL , P2INT );
824 putdot( filename , line );
825 break;
826 }
827 return;
828
829 case O_READ4:
830 case O_READLN:
831 /*
832 * Set up default
833 * file "input".
834 */
835 file = NIL;
836 filetype = nl+T1CHAR;
837 /*
838 * Determine the file implied
839 * for the read and generate
840 * code to make it the active file.
841 */
842 if (argv != NIL) {
843 codeoff();
844 ap = stkrval(argv[1], NIL , RREQ );
845 codeon();
846 if (ap == NIL)
847 argv = argv[2];
848 if (ap != NIL && ap->class == FILET) {
849 /*
850 * Got "read(f, ...", make
851 * f the active file, and save
852 * it and its type for use in
853 * processing the rest of the
854 * arguments to read.
855 */
856 file = argv[1];
857 filetype = ap->type;
858 putRV( 0, cbn , CURFILEOFFSET , P2PTR|P2STRTY );
859 putleaf( P2ICON , 0 , 0
860 , ADDTYPE( P2FTN | P2INT , P2PTR )
861 , "_UNIT" );
862 stklval(argv[1], NOFLAGS);
863 putop( P2CALL , P2INT );
864 putop( P2ASSIGN , P2PTR|P2STRTY );
865 putdot( filename , line );
866 argv = argv[2];
867 argc--;
868 } else {
869 /*
870 * Default is read from
871 * standard input.
872 */
873 putRV( 0, cbn , CURFILEOFFSET , P2PTR|P2STRTY );
874 putLV( "_input" , 0 , 0 , P2PTR|P2STRTY );
875 putop( P2ASSIGN , P2PTR|P2STRTY );
876 putdot( filename , line );
877 input->nl_flags |= NUSED;
878 }
879 } else {
880 putRV( 0, cbn , CURFILEOFFSET , P2PTR|P2STRTY );
881 putLV( "_input" , 0 , 0 , P2PTR|P2STRTY );
882 putop( P2ASSIGN , P2PTR|P2STRTY );
883 putdot( filename , line );
884 input->nl_flags |= NUSED;
885 }
886 /*
887 * Loop and process each
888 * of the arguments.
889 */
890 for (; argv != NIL; argv = argv[2]) {
891 /*
892 * Get the address of the target
893 * on the stack.
894 */
895 al = argv[1];
896 if (al == NIL)
897 continue;
898 if (al[0] != T_VAR) {
899 error("Arguments to %s must be variables, not expressions", p->symbol);
900 continue;
901 }
902 codeoff();
903 ap = stklval(al, MOD|ASGN|NOUSE);
904 codeon();
905 if (ap == NIL)
906 continue;
907 if (filetype != nl+T1CHAR) {
908 /*
909 * Generalized read, i.e.
910 * from a non-textfile.
911 */
912 if (incompat(filetype, ap, argv[1] )) {
913 error("Type mismatch in read from non-text file");
914 continue;
915 }
916 /*
917 * var := file ^;
918 */
919 ap = lvalue( al , MOD | ASGN | NOUSE , RREQ );
920 if ( isa( ap , "bsci" ) ) {
921 precheck( ap , "_RANG4" , "_RSNG4" );
922 }
923 putleaf( P2ICON , 0 , 0
924 , ADDTYPE(
925 ADDTYPE(
926 ADDTYPE(
927 p2type( filetype ) , P2PTR )
928 , P2FTN )
929 , P2PTR )
930 , "_FNIL" );
931 if (file != NIL)
932 stklval(file, NOFLAGS);
933 else /* Magic */
934 putRV( "_input" , 0 , 0
935 , P2PTR | P2STRTY );
936 putop( P2CALL , P2INT );
937 switch ( classify( filetype ) ) {
938 case TBOOL:
939 case TCHAR:
940 case TINT:
941 case TSCAL:
942 case TDOUBLE:
943 case TPTR:
944 putop( P2UNARY P2MUL
945 , p2type( filetype ) );
946 }
947 switch ( classify( filetype ) ) {
948 case TBOOL:
949 case TCHAR:
950 case TINT:
951 case TSCAL:
952 postcheck( ap );
953 /* and fall through */
954 case TDOUBLE:
955 case TPTR:
956 putop( P2ASSIGN , p2type( ap ) );
957 putdot( filename , line );
958 break;
959 default:
960 putstrop( P2STASG
961 , p2type( ap )
962 , lwidth( ap )
963 , align( ap ) );
964 putdot( filename , line );
965 break;
966 }
967 /*
968 * get(file);
969 */
970 putleaf( P2ICON , 0 , 0
971 , ADDTYPE( P2FTN | P2INT , P2PTR )
972 , "_GET" );
973 putRV( 0 , cbn , CURFILEOFFSET
974 , P2PTR|P2STRTY );
975 putop( P2CALL , P2INT );
976 putdot( filename , line );
977 continue;
978 }
979 /*
980 * if you get to here, you are reading from
981 * a text file. only possiblities are:
982 * character, integer, real, or scalar.
983 * read( f , foo , ... ) is done as
984 * foo := read( f ) with rangechecking
985 * if appropriate.
986 */
987 typ = classify(ap);
988 op = rdops(typ);
989 if (op == NIL) {
990 error("Can't read %ss from a text file", clnames[typ]);
991 continue;
992 }
993 /*
994 * left hand side of foo := read( f )
995 */
996 ap = lvalue( al , MOD|ASGN|NOUSE , RREQ );
997 if ( isa( ap , "bsci" ) ) {
998 precheck( ap , "_RANG4" , "_RSNG4" );
999 }
1000 switch ( op ) {
1001 case O_READC:
1002 readname = "_READC";
1003 readtype = P2INT;
1004 break;
1005 case O_READ4:
1006 readname = "_READ4";
1007 readtype = P2INT;
1008 break;
1009 case O_READ8:
1010 readname = "_READ8";
1011 readtype = P2DOUBLE;
1012 break;
1013 case O_READE:
1014 readname = "_READE";
1015 readtype = P2INT;
1016 break;
1017 }
1018 putleaf( P2ICON , 0 , 0
1019 , ADDTYPE( P2FTN | readtype , P2PTR )
1020 , readname );
1021 putRV( 0 , cbn , CURFILEOFFSET , P2PTR|P2STRTY );
1022 if ( op == O_READE ) {
1023 sprintf( format , PREFIXFORMAT , LABELPREFIX
1024 , listnames( ap ) );
1025 putleaf( P2ICON , 0 , 0 , P2PTR | P2CHAR
1026 , format );
1027 putop( P2LISTOP , P2INT );
1028 if (opt('s')) {
1029 standard();
1030 error("Reading of enumerated types is non-standard");
1031 }
1032 }
1033 putop( P2CALL , readtype );
1034 if ( isa( ap , "bcsi" ) ) {
1035 postcheck( ap );
1036 }
1037 putop( P2ASSIGN , p2type( ap ) );
1038 putdot( filename , line );
1039 }
1040 /*
1041 * Done with arguments.
1042 * Handle readln and
1043 * insufficient number of args.
1044 */
1045 if (p->value[0] == O_READLN) {
1046 if (filetype != nl+T1CHAR)
1047 error("Can't 'readln' a non text file");
1048 putleaf( P2ICON , 0 , 0
1049 , ADDTYPE( P2FTN | P2INT , P2PTR )
1050 , "_READLN" );
1051 putRV( 0 , cbn , CURFILEOFFSET , P2PTR|P2STRTY );
1052 putop( P2CALL , P2INT );
1053 putdot( filename , line );
1054 } else if (argc == 0)
1055 error("read requires an argument");
1056 return;
1057
1058 case O_GET:
1059 case O_PUT:
1060 if (argc != 1) {
1061 error("%s expects one argument", p->symbol);
1062 return;
1063 }
1064 putRV( 0 , cbn , CURFILEOFFSET , P2PTR|P2STRTY );
1065 putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
1066 , "_UNIT" );
1067 ap = stklval(argv[1], NOFLAGS);
1068 if (ap == NIL)
1069 return;
1070 if (ap->class != FILET) {
1071 error("Argument to %s must be a file, not %s", p->symbol, nameof(ap));
1072 return;
1073 }
1074 putop( P2CALL , P2INT );
1075 putop( P2ASSIGN , P2PTR|P2STRTY );
1076 putdot( filename , line );
1077 putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
1078 , op == O_GET ? "_GET" : "_PUT" );
1079 putRV( 0 , cbn , CURFILEOFFSET , P2PTR|P2STRTY );
1080 putop( P2CALL , P2INT );
1081 putdot( filename , line );
1082 return;
1083
1084 case O_RESET:
1085 case O_REWRITE:
1086 if (argc == 0 || argc > 2) {
1087 error("%s expects one or two arguments", p->symbol);
1088 return;
1089 }
1090 if (opt('s') && argc == 2) {
1091 standard();
1092 error("Two argument forms of reset and rewrite are non-standard");
1093 }
1094 putleaf( P2ICON , 0 , 0 , P2INT
1095 , op == O_RESET ? "_RESET" : "_REWRITE" );
1096 ap = stklval(argv[1], MOD|NOUSE);
1097 if (ap == NIL)
1098 return;
1099 if (ap->class != FILET) {
1100 error("First argument to %s must be a file, not %s", p->symbol, nameof(ap));
1101 return;
1102 }
1103 if (argc == 2) {
1104 /*
1105 * Optional second argument
1106 * is a string name of a
1107 * UNIX (R) file to be associated.
1108 */
1109 al = argv[2];
1110 al = stkrval(al[1], NOFLAGS , RREQ );
1111 if (al == NIL)
1112 return;
1113 if (classify(al) != TSTR) {
1114 error("Second argument to %s must be a string, not %s", p->symbol, nameof(al));
1115 return;
1116 }
1117 strnglen = width(al);
1118 } else {
1119 putleaf( P2ICON , 0 , 0 , P2INT , 0 );
1120 strnglen = 0;
1121 }
1122 putop( P2LISTOP , P2INT );
1123 putleaf( P2ICON , strnglen , 0 , P2INT , 0 );
1124 putop( P2LISTOP , P2INT );
1125 putleaf( P2ICON , text(ap) ? 0: width(ap->type) , 0 , P2INT , 0 );
1126 putop( P2LISTOP , P2INT );
1127 putop( P2CALL , P2INT );
1128 putdot( filename , line );
1129 return;
1130
1131 case O_NEW:
1132 case O_DISPOSE:
1133 if (argc == 0) {
1134 error("%s expects at least one argument", p->symbol);
1135 return;
1136 }
1137 putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
1138 , op == O_DISPOSE ? "_DISPOSE" :
1139 opt('t') ? "_NEWZ" : "_NEW" );
1140 ap = stklval(argv[1], op == O_NEW ? ( MOD | NOUSE ) : MOD );
1141 if (ap == NIL)
1142 return;
1143 if (ap->class != PTR) {
1144 error("(First) argument to %s must be a pointer, not %s", p->symbol, nameof(ap));
1145 return;
1146 }
1147 ap = ap->type;
1148 if (ap == NIL)
1149 return;
1150 argv = argv[2];
1151 if (argv != NIL) {
1152 if (ap->class != RECORD) {
1153 error("Record required when specifying variant tags");
1154 return;
1155 }
1156 for (; argv != NIL; argv = argv[2]) {
1157 if (ap->ptr[NL_VARNT] == NIL) {
1158 error("Too many tag fields");
1159 return;
1160 }
1161 if (!isconst(argv[1])) {
1162 error("Second and successive arguments to %s must be constants", p->symbol);
1163 return;
1164 }
1165 gconst(argv[1]);
1166 if (con.ctype == NIL)
1167 return;
1168 if (incompat(con.ctype, (ap->ptr[NL_TAG])->type , NIL )) {
1169 cerror("Specified tag constant type clashed with variant case selector type");
1170 return;
1171 }
1172 for (ap = ap->ptr[NL_VARNT]; ap != NIL; ap = ap->chain)
1173 if (ap->range[0] == con.crval)
1174 break;
1175 if (ap == NIL) {
1176 error("No variant case label value equals specified constant value");
1177 return;
1178 }
1179 ap = ap->ptr[NL_VTOREC];
1180 }
1181 }
1182 putleaf( P2ICON , width( ap ) , 0 , P2INT , 0 );
1183 putop( P2LISTOP , P2INT );
1184 putop( P2CALL , P2INT );
1185 putdot( filename , line );
1186 return;
1187
1188 case O_DATE:
1189 case O_TIME:
1190 if (argc != 1) {
1191 error("%s expects one argument", p->symbol);
1192 return;
1193 }
1194 putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
1195 , op == O_DATE ? "_DATE" : "_TIME" );
1196 ap = stklval(argv[1], MOD|NOUSE);
1197 if (ap == NIL)
1198 return;
1199 if (classify(ap) != TSTR || width(ap) != 10) {
1200 error("Argument to %s must be a alfa, not %s", p->symbol, nameof(ap));
1201 return;
1202 }
1203 putop( P2CALL , P2INT );
1204 putdot( filename , line );
1205 return;
1206
1207 case O_HALT:
1208 if (argc != 0) {
1209 error("halt takes no arguments");
1210 return;
1211 }
1212 putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
1213 , "_HALT" );
1214
1215 putop( P2UNARY P2CALL , P2INT );
1216 putdot( filename , line );
1217 noreach = 1;
1218 return;
1219
1220 case O_ARGV:
1221 if (argc != 2) {
1222 error("argv takes two arguments");
1223 return;
1224 }
1225 putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
1226 , "_ARGV" );
1227 ap = stkrval(argv[1], NIL , RREQ );
1228 if (ap == NIL)
1229 return;
1230 if (isnta(ap, "i")) {
1231 error("argv's first argument must be an integer, not %s", nameof(ap));
1232 return;
1233 }
1234 al = argv[2];
1235 ap = stklval(al[1], MOD|NOUSE);
1236 if (ap == NIL)
1237 return;
1238 if (classify(ap) != TSTR) {
1239 error("argv's second argument must be a string, not %s", nameof(ap));
1240 return;
1241 }
1242 putop( P2LISTOP , P2INT );
1243 putleaf( P2ICON , width( ap ) , 0 , P2INT , 0 );
1244 putop( P2LISTOP , P2INT );
1245 putop( P2CALL , P2INT );
1246 putdot( filename , line );
1247 return;
1248
1249 case O_STLIM:
1250 if (argc != 1) {
1251 error("stlimit requires one argument");
1252 return;
1253 }
1254 putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
1255 , "_STLIM" );
1256 ap = stkrval(argv[1], NIL , RREQ );
1257 if (ap == NIL)
1258 return;
1259 if (isnta(ap, "i")) {
1260 error("stlimit's argument must be an integer, not %s", nameof(ap));
1261 return;
1262 }
1263 putop( P2CALL , P2INT );
1264 putdot( filename , line );
1265 return;
1266
1267 case O_REMOVE:
1268 if (argc != 1) {
1269 error("remove expects one argument");
1270 return;
1271 }
1272 putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
1273 , "_REMOVE" );
1274 ap = stkrval(argv[1], NOFLAGS , RREQ );
1275 if (ap == NIL)
1276 return;
1277 if (classify(ap) != TSTR) {
1278 error("remove's argument must be a string, not %s", nameof(ap));
1279 return;
1280 }
1281 putleaf( P2ICON , width( ap ) , 0 , P2INT , 0 );
1282 putop( P2LISTOP , P2INT );
1283 putop( P2CALL , P2INT );
1284 putdot( filename , line );
1285 return;
1286
1287 case O_LLIMIT:
1288 if (argc != 2) {
1289 error("linelimit expects two arguments");
1290 return;
1291 }
1292 putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
1293 , "_LLIMIT" );
1294 ap = stklval(argv[1], NOFLAGS|NOUSE);
1295 if (ap == NIL)
1296 return;
1297 if (!text(ap)) {
1298 error("linelimit's first argument must be a text file, not %s", nameof(ap));
1299 return;
1300 }
1301 al = argv[2];
1302 ap = stkrval(al[1], NIL , RREQ );
1303 if (ap == NIL)
1304 return;
1305 if (isnta(ap, "i")) {
1306 error("linelimit's second argument must be an integer, not %s", nameof(ap));
1307 return;
1308 }
1309 putop( P2LISTOP , P2INT );
1310 putop( P2CALL , P2INT );
1311 putdot( filename , line );
1312 return;
1313 case O_PAGE:
1314 if (argc != 1) {
1315 error("page expects one argument");
1316 return;
1317 }
1318 putRV( 0 , cbn , CURFILEOFFSET , P2PTR|P2STRTY );
1319 putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
1320 , "_UNIT" );
1321 ap = stklval(argv[1], NOFLAGS);
1322 if (ap == NIL)
1323 return;
1324 if (!text(ap)) {
1325 error("Argument to page must be a text file, not %s", nameof(ap));
1326 return;
1327 }
1328 putop( P2CALL , P2INT );
1329 putop( P2ASSIGN , P2PTR|P2STRTY );
1330 putdot( filename , line );
1331 if ( opt( 't' ) ) {
1332 putleaf( P2ICON , 0 , 0
1333 , ADDTYPE( P2FTN | P2INT , P2PTR )
1334 , "_PAGE" );
1335 putRV( 0 , cbn , CURFILEOFFSET
1336 , P2PTR|P2STRTY );
1337 } else {
1338 putleaf( P2ICON , 0 , 0
1339 , ADDTYPE( P2FTN | P2INT , P2PTR )
1340 , "_fputc" );
1341 putleaf( P2ICON , '\f' , 0 , P2CHAR , 0 );
1342 putleaf( P2ICON , 0 , 0
1343 , ADDTYPE( P2FTN | P2INT , P2PTR )
1344 , "_ACTFILE" );
1345 putRV( 0 , cbn , CURFILEOFFSET
1346 , P2PTR|P2STRTY );
1347 putop( P2CALL , P2INT );
1348 putop( P2LISTOP , P2INT );
1349 }
1350 putop( P2CALL , P2INT );
1351 putdot( filename , line );
1352 return;
1353
1354 case O_PACK:
1355 if (argc != 3) {
1356 error("pack expects three arguments");
1357 return;
1358 }
1359 putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
1360 , "_PACK" );
1361 pu = "pack(a,i,z)";
1362 pua = (al = argv)[1];
1363 pui = (al = al[2])[1];
1364 puz = (al = al[2])[1];
1365 goto packunp;
1366 case O_UNPACK:
1367 if (argc != 3) {
1368 error("unpack expects three arguments");
1369 return;
1370 }
1371 putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
1372 , "_UNPACK" );
1373 pu = "unpack(z,a,i)";
1374 puz = (al = argv)[1];
1375 pua = (al = al[2])[1];
1376 pui = (al = al[2])[1];
1377packunp:
1378 ap = stkrval((int *) pui, NLNIL , RREQ );
1379 if (ap == NIL)
1380 return;
1381 ap = stklval(pua, op == O_PACK ? NOFLAGS : MOD|NOUSE);
1382 if (ap == NIL)
1383 return;
1384 if (ap->class != ARRAY) {
1385 error("%s requires a to be an unpacked array, not %s", pu, nameof(ap));
1386 return;
1387 }
1388 putop( P2LISTOP , P2INT );
1389 al = (struct nl *) stklval(puz, op == O_UNPACK ? NOFLAGS : MOD|NOUSE);
1390 if (al->class != ARRAY) {
1391 error("%s requires z to be a packed array, not %s", pu, nameof(ap));
1392 return;
1393 }
1394 if (al->type == NIL || ap->type == NIL)
1395 return;
1396 if (al->type != ap->type) {
1397 error("%s requires a and z to be arrays of the same type", pu, nameof(ap));
1398 return;
1399 }
1400 putop( P2LISTOP , P2INT );
1401 k = width(al);
1402 itemwidth = width(ap->type);
1403 ap = ap->chain;
1404 al = al->chain;
1405 if (ap->chain != NIL || al->chain != NIL) {
1406 error("%s requires a and z to be single dimension arrays", pu);
1407 return;
1408 }
1409 if (ap == NIL || al == NIL)
1410 return;
1411 /*
1412 * al is the range for z i.e. u..v
1413 * ap is the range for a i.e. m..n
1414 * i will be n-m+1
1415 * j will be v-u+1
1416 */
1417 i = ap->range[1] - ap->range[0] + 1;
1418 j = al->range[1] - al->range[0] + 1;
1419 if (i < j) {
1420 error("%s cannot have more elements in a (%d) than in z (%d)", pu, j, i);
1421 return;
1422 }
1423 /*
1424 * get n-m-(v-u) and m for the interpreter
1425 */
1426 i -= j;
1427 j = ap->range[0];
1428 putleaf( P2ICON , itemwidth , 0 , P2INT , 0 );
1429 putop( P2LISTOP , P2INT );
1430 putleaf( P2ICON , j , 0 , P2INT , 0 );
1431 putop( P2LISTOP , P2INT );
1432 putleaf( P2ICON , i , 0 , P2INT , 0 );
1433 putop( P2LISTOP , P2INT );
1434 putleaf( P2ICON , k , 0 , P2INT , 0 );
1435 putop( P2LISTOP , P2INT );
1436 putop( P2CALL , P2INT );
1437 putdot( filename , line );
1438 return;
1439 case 0:
1440 error("%s is an unimplemented 6400 extension", p->symbol);
1441 return;
1442
1443 default:
1444 panic("proc case");
1445 }
1446}
1447#endif PC