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