Annotation of 40BSD/cmd/pc0/proc.c, revision 1.1

1.1     ! root        1: /* Copyright (c) 1979 Regents of the University of California */
        !             2: 
        !             3: static char sccsid[] = "@(#)proc.c 1.3 10/28/80";
        !             4: 
        !             5: #include "whoami.h"
        !             6: #ifdef OBJ
        !             7:     /*
        !             8:      * and the rest of the file
        !             9:      */
        !            10: #include "0.h"
        !            11: #include "tree.h"
        !            12: #include "opcode.h"
        !            13: #include "objfmt.h"
        !            14: 
        !            15: /*
        !            16:  * The following array is used to determine which classes may be read
        !            17:  * from textfiles. It is indexed by the return value from classify.
        !            18:  */
        !            19: #define rdops(x) rdxxxx[(x)-(TFIRST)]
        !            20: 
        !            21: int rdxxxx[] = {
        !            22:        0,              /* -7 file types */
        !            23:        0,              /* -6 record types */
        !            24:        0,              /* -5 array types */
        !            25:        O_READE,        /* -4 scalar types */
        !            26:        0,              /* -3 pointer types */
        !            27:        0,              /* -2 set types */
        !            28:        0,              /* -1 string types */
        !            29:        0,              /*  0 nil, no type */
        !            30:        O_READE,        /*  1 boolean */
        !            31:        O_READC,        /*  2 character */
        !            32:        O_READ4,        /*  3 integer */
        !            33:        O_READ8         /*  4 real */
        !            34: };
        !            35: 
        !            36: /*
        !            37:  * Proc handles procedure calls.
        !            38:  * Non-builtin procedures are "buck-passed" to func (with a flag
        !            39:  * indicating that they are actually procedures.
        !            40:  * builtin procedures are handled here.
        !            41:  */
        !            42: proc(r)
        !            43:        int *r;
        !            44: {
        !            45:        register struct nl *p;
        !            46:        register int *alv, *al, op;
        !            47:        struct nl *filetype, *ap;
        !            48:        int argc, *argv, typ, fmtspec, strfmt, stkcnt, *file;
        !            49:        char fmt, format[20], *strptr;
        !            50:        int prec, field, strnglen, fmtlen, fmtstart, pu;
        !            51:        int *pua, *pui, *puz;
        !            52:        int i, j, k;
        !            53:        int itemwidth;
        !            54: 
        !            55: #define        CONPREC 4
        !            56: #define        VARPREC 8
        !            57: #define        CONWIDTH 1
        !            58: #define        VARWIDTH 2
        !            59: #define SKIP 16
        !            60: 
        !            61:        /*
        !            62:         * Verify that the name is
        !            63:         * defined and is that of a
        !            64:         * procedure.
        !            65:         */
        !            66:        p = lookup(r[2]);
        !            67:        if (p == NIL) {
        !            68:                rvlist(r[3]);
        !            69:                return;
        !            70:        }
        !            71:        if (p->class != PROC && p->class != FPROC) {
        !            72:                error("Can't call %s, its %s not a procedure", p->symbol, classes[p->class]);
        !            73:                rvlist(r[3]);
        !            74:                return;
        !            75:        }
        !            76:        argv = r[3];
        !            77: 
        !            78:        /*
        !            79:         * Call handles user defined
        !            80:         * procedures and functions.
        !            81:         */
        !            82:        if (bn != 0) {
        !            83:                call(p, argv, PROC, bn);
        !            84:                return;
        !            85:        }
        !            86: 
        !            87:        /*
        !            88:         * Call to built-in procedure.
        !            89:         * Count the arguments.
        !            90:         */
        !            91:        argc = 0;
        !            92:        for (al = argv; al != NIL; al = al[2])
        !            93:                argc++;
        !            94: 
        !            95:        /*
        !            96:         * Switch on the operator
        !            97:         * associated with the built-in
        !            98:         * procedure in the namelist
        !            99:         */
        !           100:        op = p->value[0] &~ NSTAND;
        !           101:        if (opt('s') && (p->value[0] & NSTAND)) {
        !           102:                standard();
        !           103:                error("%s is a nonstandard procedure", p->symbol);
        !           104:        }
        !           105:        switch (op) {
        !           106: 
        !           107:        case O_ABORT:
        !           108:                if (argc != 0)
        !           109:                        error("null takes no arguments");
        !           110:                return;
        !           111: 
        !           112:        case O_FLUSH:
        !           113:                if (argc == 0) {
        !           114:                        put(1, O_MESSAGE);
        !           115:                        return;
        !           116:                }
        !           117:                if (argc != 1) {
        !           118:                        error("flush takes at most one argument");
        !           119:                        return;
        !           120:                }
        !           121:                ap = stkrval(argv[1], NIL , RREQ );
        !           122:                if (ap == NIL)
        !           123:                        return;
        !           124:                if (ap->class != FILET) {
        !           125:                        error("flush's argument must be a file, not %s", nameof(ap));
        !           126:                        return;
        !           127:                }
        !           128:                put(1, op);
        !           129:                return;
        !           130: 
        !           131:        case O_MESSAGE:
        !           132:        case O_WRITEF:
        !           133:        case O_WRITLN:
        !           134:                /*
        !           135:                 * Set up default file "output"'s type
        !           136:                 */
        !           137:                file = NIL;
        !           138:                filetype = nl+T1CHAR;
        !           139:                /*
        !           140:                 * Determine the file implied
        !           141:                 * for the write and generate
        !           142:                 * code to make it the active file.
        !           143:                 */
        !           144:                if (op == O_MESSAGE) {
        !           145:                        /*
        !           146:                         * For message, all that matters
        !           147:                         * is that the filetype is
        !           148:                         * a character file.
        !           149:                         * Thus "output" will suit us fine.
        !           150:                         */
        !           151:                        put(1, O_MESSAGE);
        !           152:                } else if (argv != NIL && (al = argv[1])[0] != T_WEXP) {
        !           153:                        /*
        !           154:                         * If there is a first argument which has
        !           155:                         * no write widths, then it is potentially
        !           156:                         * a file name.
        !           157:                         */
        !           158:                        codeoff();
        !           159:                        ap = stkrval(argv[1], NIL , RREQ );
        !           160:                        codeon();
        !           161:                        if (ap == NIL)
        !           162:                                argv = argv[2];
        !           163:                        if (ap != NIL && ap->class == FILET) {
        !           164:                                /*
        !           165:                                 * Got "write(f, ...", make
        !           166:                                 * f the active file, and save
        !           167:                                 * it and its type for use in
        !           168:                                 * processing the rest of the
        !           169:                                 * arguments to write.
        !           170:                                 */
        !           171:                                file = argv[1];
        !           172:                                filetype = ap->type;
        !           173:                                stkrval(argv[1], NIL , RREQ );
        !           174:                                put(1, O_UNIT);
        !           175:                                /*
        !           176:                                 * Skip over the first argument
        !           177:                                 */
        !           178:                                argv = argv[2];
        !           179:                                argc--;
        !           180:                        } else
        !           181:                                /*
        !           182:                                 * Set up for writing on 
        !           183:                                 * standard output.
        !           184:                                 */
        !           185:                                put(1, O_UNITOUT);
        !           186:                } else
        !           187:                        put(1, O_UNITOUT);
        !           188:                /*
        !           189:                 * Loop and process each
        !           190:                 * of the arguments.
        !           191:                 */
        !           192:                for (; argv != NIL; argv = argv[2]) {
        !           193:                        /*
        !           194:                         * fmtspec indicates the type (CONstant or VARiable)
        !           195:                         *      and number (none, WIDTH, and/or PRECision)
        !           196:                         *      of the fields in the printf format for this
        !           197:                         *      output variable.
        !           198:                         * stkcnt is the number of longs pushed on the stack
        !           199:                         * fmt is the format output indicator (D, E, F, O, X, S)
        !           200:                         * fmtstart = 0 for leading blank; = 1 for no blank
        !           201:                         */
        !           202:                        fmtspec = NIL;
        !           203:                        stkcnt = 0;
        !           204:                        fmt = 'D';
        !           205:                        fmtstart = 1;
        !           206:                        al = argv[1];
        !           207:                        if (al == NIL)
        !           208:                                continue;
        !           209:                        if (al[0] == T_WEXP)
        !           210:                                alv = al[1];
        !           211:                        else
        !           212:                                alv = al;
        !           213:                        if (alv == NIL)
        !           214:                                continue;
        !           215:                        codeoff();
        !           216:                        ap = stkrval(alv, NIL , RREQ );
        !           217:                        codeon();
        !           218:                        if (ap == NIL)
        !           219:                                continue;
        !           220:                        typ = classify(ap);
        !           221:                        if (al[0] == T_WEXP) {
        !           222:                                /*
        !           223:                                 * Handle width expressions.
        !           224:                                 * The basic game here is that width
        !           225:                                 * expressions get evaluated. If they
        !           226:                                 * are constant, the value is placed
        !           227:                                 * directly in the format string.
        !           228:                                 * Otherwise the value is pushed onto
        !           229:                                 * the stack and an indirection is
        !           230:                                 * put into the format string.
        !           231:                                 */
        !           232:                                if (al[3] == OCT)
        !           233:                                        fmt = 'O';
        !           234:                                else if (al[3] == HEX)
        !           235:                                        fmt = 'X';
        !           236:                                else if (al[3] != NIL) {
        !           237:                                        /*
        !           238:                                         * Evaluate second format spec
        !           239:                                         */
        !           240:                                        if ( constval(al[3])
        !           241:                                            && isa( con.ctype , "i" ) ) {
        !           242:                                                fmtspec += CONPREC;
        !           243:                                                prec = con.crval;
        !           244:                                        } else {
        !           245:                                                fmtspec += VARPREC;
        !           246:                                        }
        !           247:                                        fmt = 'f';
        !           248:                                        switch ( typ ) {
        !           249:                                        case TINT:
        !           250:                                                if ( opt( 's' ) ) {
        !           251:                                                    standard();
        !           252:                                                    error("Writing %ss with two write widths is non-standard", clnames[typ]);
        !           253:                                                }
        !           254:                                                /* and fall through */
        !           255:                                        case TDOUBLE:
        !           256:                                                break;
        !           257:                                        default:
        !           258:                                                error("Cannot write %ss with two write widths", clnames[typ]);
        !           259:                                                continue;
        !           260:                                        }
        !           261:                                }
        !           262:                                /*
        !           263:                                 * Evaluate first format spec
        !           264:                                 */
        !           265:                                if (al[2] != NIL) {
        !           266:                                        if ( constval(al[2])
        !           267:                                            && isa( con.ctype , "i" ) ) {
        !           268:                                                fmtspec += CONWIDTH;
        !           269:                                                field = con.crval;
        !           270:                                        } else {
        !           271:                                                fmtspec += VARWIDTH;
        !           272:                                        }
        !           273:                                }
        !           274:                                if ((fmtspec & CONPREC) && prec < 0 ||
        !           275:                                    (fmtspec & CONWIDTH) && field < 0) {
        !           276:                                        error("Negative widths are not allowed");
        !           277:                                        continue;
        !           278:                                }
        !           279:                        }
        !           280:                        if (filetype != nl+T1CHAR) {
        !           281:                                if (fmt == 'O' || fmt == 'X') {
        !           282:                                        error("Oct/hex allowed only on text files");
        !           283:                                        continue;
        !           284:                                }
        !           285:                                if (fmtspec) {
        !           286:                                        error("Write widths allowed only on text files");
        !           287:                                        continue;
        !           288:                                }
        !           289:                                /*
        !           290:                                 * Generalized write, i.e.
        !           291:                                 * to a non-textfile.
        !           292:                                 */
        !           293:                                stkrval(file, NIL , RREQ );
        !           294:                                put(1, O_FNIL);
        !           295:                                /*
        !           296:                                 * file^ := ...
        !           297:                                 */
        !           298:                                ap = rvalue(argv[1], NIL);
        !           299:                                if (ap == NIL)
        !           300:                                        continue;
        !           301:                                if (incompat(ap, filetype, argv[1])) {
        !           302:                                        cerror("Type mismatch in write to non-text file");
        !           303:                                        continue;
        !           304:                                }
        !           305:                                convert(ap, filetype);
        !           306:                                put(2, O_AS, width(filetype));
        !           307:                                /*
        !           308:                                 * put(file)
        !           309:                                 */
        !           310:                                put(1, O_PUT);
        !           311:                                continue;
        !           312:                        }
        !           313:                        /*
        !           314:                         * Write to a textfile
        !           315:                         *
        !           316:                         * Evaluate the expression
        !           317:                         * to be written.
        !           318:                         */
        !           319:                        if (fmt == 'O' || fmt == 'X') {
        !           320:                                if (opt('s')) {
        !           321:                                        standard();
        !           322:                                        error("Oct and hex are non-standard");
        !           323:                                }
        !           324:                                if (typ == TSTR || typ == TDOUBLE) {
        !           325:                                        error("Can't write %ss with oct/hex", clnames[typ]);
        !           326:                                        continue;
        !           327:                                }
        !           328:                                if (typ == TCHAR || typ == TBOOL)
        !           329:                                        typ = TINT;
        !           330:                        }
        !           331:                        /*
        !           332:                         * Place the arguement on the stack. If there is
        !           333:                         * no format specified by the programmer, implement
        !           334:                         * the default.
        !           335:                         */
        !           336:                        switch (typ) {
        !           337:                        case TINT:
        !           338:                                if (fmt != 'f') {
        !           339:                                        ap = stkrval(alv, NIL , RREQ );
        !           340:                                        stkcnt++;
        !           341:                                } else {
        !           342:                                        ap = stkrval(alv, NIL , RREQ );
        !           343:                                        put(1, O_ITOD);
        !           344:                                        stkcnt += 2;
        !           345:                                        typ = TDOUBLE;
        !           346:                                        goto tdouble;
        !           347:                                }
        !           348:                                if (fmtspec == NIL) {
        !           349:                                        if (fmt == 'D')
        !           350:                                                field = 10;
        !           351:                                        else if (fmt == 'X')
        !           352:                                                field = 8;
        !           353:                                        else if (fmt == 'O')
        !           354:                                                field = 11;
        !           355:                                        else
        !           356:                                                panic("fmt1");
        !           357:                                        fmtspec = CONWIDTH;
        !           358:                                }
        !           359:                                break;
        !           360:                        case TCHAR:
        !           361:                             tchar:
        !           362:                                ap = stkrval(alv, NIL , RREQ );
        !           363:                                stkcnt++;
        !           364:                                fmt = 'c';
        !           365:                                break;
        !           366:                        case TSCAL:
        !           367:                                warning();
        !           368:                                if (opt('s')) {
        !           369:                                        standard();
        !           370:                                }
        !           371:                                error("Writing scalars to text files is non-standard");
        !           372:                        case TBOOL:
        !           373:                                stkrval(alv, NIL , RREQ );
        !           374:                                put(2, O_NAM, listnames(ap));
        !           375:                                stkcnt++;
        !           376:                                fmt = 's';
        !           377:                                break;
        !           378:                        case TDOUBLE:
        !           379:                                ap = stkrval(alv, TDOUBLE , RREQ );
        !           380:                                stkcnt += 2;
        !           381:                             tdouble:
        !           382:                                switch (fmtspec) {
        !           383:                                case NIL:
        !           384:                                        field = 21;
        !           385:                                        prec = 14;
        !           386:                                        fmt = 'E';
        !           387:                                        fmtspec = CONWIDTH + CONPREC;
        !           388:                                        break;
        !           389:                                case CONWIDTH:
        !           390:                                        if (--field < 1)
        !           391:                                                field = 1;
        !           392:                                        prec = field - 7;
        !           393:                                        if (prec < 1)
        !           394:                                                prec = 1;
        !           395:                                        fmtspec += CONPREC;
        !           396:                                        fmt = 'E';
        !           397:                                        break;
        !           398:                                case CONWIDTH + CONPREC:
        !           399:                                case CONWIDTH + VARPREC:
        !           400:                                        if (--field < 1)
        !           401:                                                field = 1;
        !           402:                                }
        !           403:                                format[0] = ' ';
        !           404:                                fmtstart = 0;
        !           405:                                break;
        !           406:                        case TSTR:
        !           407:                                constval( alv );
        !           408:                                switch ( classify( con.ctype ) ) {
        !           409:                                    case TCHAR:
        !           410:                                        typ = TCHAR;
        !           411:                                        goto tchar;
        !           412:                                    case TSTR:
        !           413:                                        strptr = con.cpval;
        !           414:                                        for (strnglen = 0;  *strptr++;  strnglen++) /* void */;
        !           415:                                        strptr = con.cpval;
        !           416:                                        break;
        !           417:                                    default:
        !           418:                                        strnglen = width(ap);
        !           419:                                        break;
        !           420:                                }
        !           421:                                fmt = 's';
        !           422:                                strfmt = fmtspec;
        !           423:                                if (fmtspec == NIL) {
        !           424:                                        fmtspec = SKIP;
        !           425:                                        break;
        !           426:                                }
        !           427:                                if (fmtspec & CONWIDTH) {
        !           428:                                        if (field <= strnglen) {
        !           429:                                                fmtspec = SKIP;
        !           430:                                                break;
        !           431:                                        } else
        !           432:                                                field -= strnglen;
        !           433:                                }
        !           434:                                /*
        !           435:                                 * push string to implement leading blank padding
        !           436:                                 */
        !           437:                                put(2, O_LVCON, 2);
        !           438:                                putstr("", 0);
        !           439:                                stkcnt++;
        !           440:                                break;
        !           441:                        default:
        !           442:                                error("Can't write %ss to a text file", clnames[typ]);
        !           443:                                continue;
        !           444:                        }
        !           445:                        /*
        !           446:                         * If there is a variable precision, evaluate it onto
        !           447:                         * the stack
        !           448:                         */
        !           449:                        if (fmtspec & VARPREC) {
        !           450:                                ap = stkrval(al[3], NIL , RREQ );
        !           451:                                if (ap == NIL)
        !           452:                                        continue;
        !           453:                                if (isnta(ap,"i")) {
        !           454:                                        error("Second write width must be integer, not %s", nameof(ap));
        !           455:                                        continue;
        !           456:                                }
        !           457:                                if ( opt( 't' ) ) {
        !           458:                                    put(3, O_MAX, 0, 0);
        !           459:                                }
        !           460:                                stkcnt++;
        !           461:                        }
        !           462:                        /*
        !           463:                         * If there is a variable width, evaluate it onto
        !           464:                         * the stack
        !           465:                         */
        !           466:                        if (fmtspec & VARWIDTH) {
        !           467:                                if ( ( typ == TDOUBLE && fmtspec == VARWIDTH )
        !           468:                                    || typ == TSTR ) {
        !           469:                                        i = sizes[cbn].om_off -= sizeof(int);
        !           470:                                        if (i < sizes[cbn].om_max)
        !           471:                                                sizes[cbn].om_max = i;
        !           472:                                        put(2, O_LV | cbn << 8 + INDX, i);
        !           473:                                }
        !           474:                                ap = stkrval(al[2], NIL , RREQ );
        !           475:                                if (ap == NIL)
        !           476:                                        continue;
        !           477:                                if (isnta(ap,"i")) {
        !           478:                                        error("First write width must be integer, not %s", nameof(ap));
        !           479:                                        continue;
        !           480:                                }
        !           481:                                stkcnt++;
        !           482:                                /*
        !           483:                                 * Perform special processing on widths based
        !           484:                                 * on data type 
        !           485:                                 */
        !           486:                                switch (typ) {
        !           487:                                case TDOUBLE:
        !           488:                                        if (fmtspec == VARWIDTH) {
        !           489:                                                fmt = 'E';
        !           490:                                                put(1, O_AS4);
        !           491:                                                put(2, O_RV4 | cbn << 8 + INDX, i);
        !           492:                                                put(3, O_MAX, 8, 1);
        !           493:                                                put(2, O_RV4 | cbn << 8 + INDX, i);
        !           494:                                                stkcnt++;
        !           495:                                                fmtspec += VARPREC;
        !           496:                                        }
        !           497:                                        put(3, O_MAX, 1, 1);
        !           498:                                        break;
        !           499:                                case TSTR:
        !           500:                                        put(1, O_AS4);
        !           501:                                        put(2, O_RV4 | cbn << 8 + INDX, i);
        !           502:                                        put(3, O_MAX, strnglen, 0);
        !           503:                                        break;
        !           504:                                default:
        !           505:                                        if ( opt( 't' ) ) {
        !           506:                                            put(3, O_MAX, 0, 0);
        !           507:                                        }
        !           508:                                        break;
        !           509:                                }
        !           510:                        }
        !           511:                        /*
        !           512:                         * Generate the format string
        !           513:                         */
        !           514:                        switch (fmtspec) {
        !           515:                        default:
        !           516:                                panic("fmt2");
        !           517:                        case NIL:
        !           518:                                if (fmt == 'c')
        !           519:                                        put(1, O_WRITEC);
        !           520:                                else  {
        !           521:                                        sprintf(&format[1], "%%%c", fmt);
        !           522:                                        goto fmtgen;
        !           523:                                }
        !           524:                        case SKIP:
        !           525:                                break;
        !           526:                        case CONWIDTH:
        !           527:                                sprintf(&format[1], "%%%1D%c", field, fmt);
        !           528:                                goto fmtgen;
        !           529:                        case VARWIDTH:
        !           530:                                sprintf(&format[1], "%%*%c", fmt);
        !           531:                                goto fmtgen;
        !           532:                        case CONWIDTH + CONPREC:
        !           533:                                sprintf(&format[1], "%%%1D.%1D%c", field, prec, fmt);
        !           534:                                goto fmtgen;
        !           535:                        case CONWIDTH + VARPREC:
        !           536:                                sprintf(&format[1], "%%%1D.*%c", field, fmt);
        !           537:                                goto fmtgen;
        !           538:                        case VARWIDTH + CONPREC:
        !           539:                                sprintf(&format[1], "%%*.%1D%c", prec, fmt);
        !           540:                                goto fmtgen;
        !           541:                        case VARWIDTH + VARPREC:
        !           542:                                sprintf(&format[1], "%%*.*%c", fmt);
        !           543:                        fmtgen:
        !           544:                                fmtlen = lenstr(&format[fmtstart], 0);
        !           545:                                put(2, O_LVCON, fmtlen);
        !           546:                                putstr(&format[fmtstart], 0);
        !           547:                                put(1, O_FILE);
        !           548:                                stkcnt += 2;
        !           549:                                put(2, O_WRITEF, stkcnt);
        !           550:                        }
        !           551:                        /*
        !           552:                         * Write the string after its blank padding
        !           553:                         */
        !           554:                        if (typ == TSTR) {
        !           555:                                put(1, O_FILE);
        !           556:                                put(2, O_CON24, 1);
        !           557:                                if (strfmt & VARWIDTH) {
        !           558:                                        put(2, O_RV4 | cbn << 8 + INDX , i );
        !           559:                                        put(2, O_MIN, strnglen);
        !           560:                                } else {
        !           561:                                        if ((fmtspec & SKIP) &&
        !           562:                                           (strfmt & CONWIDTH)) {
        !           563:                                                strnglen = field;
        !           564:                                        }
        !           565:                                        put(2, O_CON24, strnglen);
        !           566:                                }
        !           567:                                ap = stkrval(alv, NIL , RREQ );
        !           568:                                put(1, O_WRITES);
        !           569:                        }
        !           570:                }
        !           571:                /*
        !           572:                 * Done with arguments.
        !           573:                 * Handle writeln and
        !           574:                 * insufficent number of args.
        !           575:                 */
        !           576:                switch (p->value[0] &~ NSTAND) {
        !           577:                        case O_WRITEF:
        !           578:                                if (argc == 0)
        !           579:                                        error("Write requires an argument");
        !           580:                                break;
        !           581:                        case O_MESSAGE:
        !           582:                                if (argc == 0)
        !           583:                                        error("Message requires an argument");
        !           584:                        case O_WRITLN:
        !           585:                                if (filetype != nl+T1CHAR)
        !           586:                                        error("Can't 'writeln' a non text file");
        !           587:                                put(1, O_WRITLN);
        !           588:                                break;
        !           589:                }
        !           590:                return;
        !           591: 
        !           592:        case O_READ4:
        !           593:        case O_READLN:
        !           594:                /*
        !           595:                 * Set up default
        !           596:                 * file "input".
        !           597:                 */
        !           598:                file = NIL;
        !           599:                filetype = nl+T1CHAR;
        !           600:                /*
        !           601:                 * Determine the file implied
        !           602:                 * for the read and generate
        !           603:                 * code to make it the active file.
        !           604:                 */
        !           605:                if (argv != NIL) {
        !           606:                        codeoff();
        !           607:                        ap = stkrval(argv[1], NIL , RREQ );
        !           608:                        codeon();
        !           609:                        if (ap == NIL)
        !           610:                                argv = argv[2];
        !           611:                        if (ap != NIL && ap->class == FILET) {
        !           612:                                /*
        !           613:                                 * Got "read(f, ...", make
        !           614:                                 * f the active file, and save
        !           615:                                 * it and its type for use in
        !           616:                                 * processing the rest of the
        !           617:                                 * arguments to read.
        !           618:                                 */
        !           619:                                file = argv[1];
        !           620:                                filetype = ap->type;
        !           621:                                stkrval(argv[1], NIL , RREQ );
        !           622:                                put(1, O_UNIT);
        !           623:                                argv = argv[2];
        !           624:                                argc--;
        !           625:                        } else {
        !           626:                                /*
        !           627:                                 * Default is read from
        !           628:                                 * standard input.
        !           629:                                 */
        !           630:                                put(1, O_UNITINP);
        !           631:                                input->nl_flags |= NUSED;
        !           632:                        }
        !           633:                } else {
        !           634:                        put(1, O_UNITINP);
        !           635:                        input->nl_flags |= NUSED;
        !           636:                }
        !           637:                /*
        !           638:                 * Loop and process each
        !           639:                 * of the arguments.
        !           640:                 */
        !           641:                for (; argv != NIL; argv = argv[2]) {
        !           642:                        /*
        !           643:                         * Get the address of the target
        !           644:                         * on the stack.
        !           645:                         */
        !           646:                        al = argv[1];
        !           647:                        if (al == NIL)
        !           648:                                continue;
        !           649:                        if (al[0] != T_VAR) {
        !           650:                                error("Arguments to %s must be variables, not expressions", p->symbol);
        !           651:                                continue;
        !           652:                        }
        !           653:                        ap = stklval(al, MOD|ASGN|NOUSE);
        !           654:                        if (ap == NIL)
        !           655:                                continue;
        !           656:                        if (filetype != nl+T1CHAR) {
        !           657:                                /*
        !           658:                                 * Generalized read, i.e.
        !           659:                                 * from a non-textfile.
        !           660:                                 */
        !           661:                                if (incompat(filetype, ap, argv[1] )) {
        !           662:                                        error("Type mismatch in read from non-text file");
        !           663:                                        continue;
        !           664:                                }
        !           665:                                /*
        !           666:                                 * var := file ^;
        !           667:                                 */
        !           668:                                if (file != NIL)
        !           669:                                        stkrval(file, NIL , RREQ );
        !           670:                                else /* Magic */
        !           671:                                        put(2, O_RV2, input->value[0]);
        !           672:                                put(1, O_FNIL);
        !           673:                                put(2, O_IND, width(filetype));
        !           674:                                convert(filetype, ap);
        !           675:                                if (isa(ap, "bsci"))
        !           676:                                        rangechk(ap, ap);
        !           677:                                put(2, O_AS, width(ap));
        !           678:                                /*
        !           679:                                 * get(file);
        !           680:                                 */
        !           681:                                put(1, O_GET);
        !           682:                                continue;
        !           683:                        }
        !           684:                        typ = classify(ap);
        !           685:                        op = rdops(typ);
        !           686:                        if (op == NIL) {
        !           687:                                error("Can't read %ss from a text file", clnames[typ]);
        !           688:                                continue;
        !           689:                        }
        !           690:                        if (op != O_READE)
        !           691:                                put(1, op);
        !           692:                        else {
        !           693:                                put(2, op, listnames(ap));
        !           694:                                warning();
        !           695:                                if (opt('s')) {
        !           696:                                        standard();
        !           697:                                }
        !           698:                                error("Reading scalars from text files is non-standard");
        !           699:                        }
        !           700:                        /*
        !           701:                         * Data read is on the stack.
        !           702:                         * Assign it.
        !           703:                         */
        !           704:                        if (op != O_READ8 && op != O_READE)
        !           705:                                rangechk(ap, op == O_READC ? ap : nl+T4INT);
        !           706:                        gen(O_AS2, O_AS2, width(ap),
        !           707:                                op == O_READ8 ? 8 : op == O_READ4 ? 4 : 2);
        !           708:                }
        !           709:                /*
        !           710:                 * Done with arguments.
        !           711:                 * Handle readln and
        !           712:                 * insufficient number of args.
        !           713:                 */
        !           714:                if (p->value[0] == O_READLN) {
        !           715:                        if (filetype != nl+T1CHAR)
        !           716:                                error("Can't 'readln' a non text file");
        !           717:                        put(1, O_READLN);
        !           718:                }
        !           719:                else if (argc == 0)
        !           720:                        error("read requires an argument");
        !           721:                return;
        !           722: 
        !           723:        case O_GET:
        !           724:        case O_PUT:
        !           725:                if (argc != 1) {
        !           726:                        error("%s expects one argument", p->symbol);
        !           727:                        return;
        !           728:                }
        !           729:                ap = stkrval(argv[1], NIL , RREQ );
        !           730:                if (ap == NIL)
        !           731:                        return;
        !           732:                if (ap->class != FILET) {
        !           733:                        error("Argument to %s must be a file, not %s", p->symbol, nameof(ap));
        !           734:                        return;
        !           735:                }
        !           736:                put(1, O_UNIT);
        !           737:                put(1, op);
        !           738:                return;
        !           739: 
        !           740:        case O_RESET:
        !           741:        case O_REWRITE:
        !           742:                if (argc == 0 || argc > 2) {
        !           743:                        error("%s expects one or two arguments", p->symbol);
        !           744:                        return;
        !           745:                }
        !           746:                if (opt('s') && argc == 2) {
        !           747:                        standard();
        !           748:                        error("Two argument forms of reset and rewrite are non-standard");
        !           749:                }
        !           750:                ap = stklval(argv[1], MOD|NOUSE);
        !           751:                if (ap == NIL)
        !           752:                        return;
        !           753:                if (ap->class != FILET) {
        !           754:                        error("First argument to %s must be a file, not %s", p->symbol, nameof(ap));
        !           755:                        return;
        !           756:                }
        !           757:                if (argc == 2) {
        !           758:                        /*
        !           759:                         * Optional second argument
        !           760:                         * is a string name of a
        !           761:                         * UNIX (R) file to be associated.
        !           762:                         */
        !           763:                        al = argv[2];
        !           764:                        al = stkrval(al[1], NOFLAGS , RREQ );
        !           765:                        if (al == NIL)
        !           766:                                return;
        !           767:                        if (classify(al) != TSTR) {
        !           768:                                error("Second argument to %s must be a string, not %s", p->symbol, nameof(al));
        !           769:                                return;
        !           770:                        }
        !           771:                        strnglen = width(al);
        !           772:                } else {
        !           773:                        put(2, O_CON24, NIL);
        !           774:                        strnglen = 0;
        !           775:                }
        !           776:                put(2, O_CON24, strnglen);
        !           777:                put(2, O_CON24, text(ap) ? 0: width(ap->type));
        !           778:                put(1, op);
        !           779:                return;
        !           780: 
        !           781:        case O_NEW:
        !           782:        case O_DISPOSE:
        !           783:                if (argc == 0) {
        !           784:                        error("%s expects at least one argument", p->symbol);
        !           785:                        return;
        !           786:                }
        !           787:                ap = stklval(argv[1], op == O_NEW ? ( MOD | NOUSE ) : MOD );
        !           788:                if (ap == NIL)
        !           789:                        return;
        !           790:                if (ap->class != PTR) {
        !           791:                        error("(First) argument to %s must be a pointer, not %s", p->symbol, nameof(ap));
        !           792:                        return;
        !           793:                }
        !           794:                ap = ap->type;
        !           795:                if (ap == NIL)
        !           796:                        return;
        !           797:                argv = argv[2];
        !           798:                if (argv != NIL) {
        !           799:                        if (ap->class != RECORD) {
        !           800:                                error("Record required when specifying variant tags");
        !           801:                                return;
        !           802:                        }
        !           803:                        for (; argv != NIL; argv = argv[2]) {
        !           804:                                if (ap->ptr[NL_VARNT] == NIL) {
        !           805:                                        error("Too many tag fields");
        !           806:                                        return;
        !           807:                                }
        !           808:                                if (!isconst(argv[1])) {
        !           809:                                        error("Second and successive arguments to %s must be constants", p->symbol);
        !           810:                                        return;
        !           811:                                }
        !           812:                                gconst(argv[1]);
        !           813:                                if (con.ctype == NIL)
        !           814:                                        return;
        !           815:                                if (incompat(con.ctype, (ap->ptr[NL_TAG])->type , NIL )) {
        !           816:                                        cerror("Specified tag constant type clashed with variant case selector type");
        !           817:                                        return;
        !           818:                                }
        !           819:                                for (ap = ap->ptr[NL_VARNT]; ap != NIL; ap = ap->chain)
        !           820:                                        if (ap->range[0] == con.crval)
        !           821:                                                break;
        !           822:                                if (ap == NIL) {
        !           823:                                        error("No variant case label value equals specified constant value");
        !           824:                                        return;
        !           825:                                }
        !           826:                                ap = ap->ptr[NL_VTOREC];
        !           827:                        }
        !           828:                }
        !           829:                put(2, op, width(ap));
        !           830:                return;
        !           831: 
        !           832:        case O_DATE:
        !           833:        case O_TIME:
        !           834:                if (argc != 1) {
        !           835:                        error("%s expects one argument", p->symbol);
        !           836:                        return;
        !           837:                }
        !           838:                ap = stklval(argv[1], MOD|NOUSE);
        !           839:                if (ap == NIL)
        !           840:                        return;
        !           841:                if (classify(ap) != TSTR || width(ap) != 10) {
        !           842:                        error("Argument to %s must be a alfa, not %s", p->symbol, nameof(ap));
        !           843:                        return;
        !           844:                }
        !           845:                put(1, op);
        !           846:                return;
        !           847: 
        !           848:        case O_HALT:
        !           849:                if (argc != 0) {
        !           850:                        error("halt takes no arguments");
        !           851:                        return;
        !           852:                }
        !           853:                put(1, op);
        !           854:                noreach = 1;
        !           855:                return;
        !           856: 
        !           857:        case O_ARGV:
        !           858:                if (argc != 2) {
        !           859:                        error("argv takes two arguments");
        !           860:                        return;
        !           861:                }
        !           862:                ap = stkrval(argv[1], NIL , RREQ );
        !           863:                if (ap == NIL)
        !           864:                        return;
        !           865:                if (isnta(ap, "i")) {
        !           866:                        error("argv's first argument must be an integer, not %s", nameof(ap));
        !           867:                        return;
        !           868:                }
        !           869:                al = argv[2];
        !           870:                ap = stklval(al[1], MOD|NOUSE);
        !           871:                if (ap == NIL)
        !           872:                        return;
        !           873:                if (classify(ap) != TSTR) {
        !           874:                        error("argv's second argument must be a string, not %s", nameof(ap));
        !           875:                        return;
        !           876:                }
        !           877:                put(2, op, width(ap));
        !           878:                return;
        !           879: 
        !           880:        case O_STLIM:
        !           881:                if (argc != 1) {
        !           882:                        error("stlimit requires one argument");
        !           883:                        return;
        !           884:                }
        !           885:                ap = stkrval(argv[1], NIL , RREQ );
        !           886:                if (ap == NIL)
        !           887:                        return;
        !           888:                if (isnta(ap, "i")) {
        !           889:                        error("stlimit's argument must be an integer, not %s", nameof(ap));
        !           890:                        return;
        !           891:                }
        !           892:                if (width(ap) != 4)
        !           893:                        put(1, O_STOI);
        !           894:                put(1, op);
        !           895:                return;
        !           896: 
        !           897:        case O_REMOVE:
        !           898:                if (argc != 1) {
        !           899:                        error("remove expects one argument");
        !           900:                        return;
        !           901:                }
        !           902:                ap = stkrval(argv[1], NOFLAGS , RREQ );
        !           903:                if (ap == NIL)
        !           904:                        return;
        !           905:                if (classify(ap) != TSTR) {
        !           906:                        error("remove's argument must be a string, not %s", nameof(ap));
        !           907:                        return;
        !           908:                }
        !           909:                put(2, O_CON24, width(ap));
        !           910:                put(1, op);
        !           911:                return;
        !           912: 
        !           913:        case O_LLIMIT:
        !           914:                if (argc != 2) {
        !           915:                        error("linelimit expects two arguments");
        !           916:                        return;
        !           917:                }
        !           918:                ap = stklval(argv[1], NOFLAGS|NOUSE);
        !           919:                if (ap == NIL)
        !           920:                        return;
        !           921:                if (!text(ap)) {
        !           922:                        error("linelimit's first argument must be a text file, not %s", nameof(ap));
        !           923:                        return;
        !           924:                }
        !           925:                al = argv[2];
        !           926:                ap = stkrval(al[1], NIL , RREQ );
        !           927:                if (ap == NIL)
        !           928:                        return;
        !           929:                if (isnta(ap, "i")) {
        !           930:                        error("linelimit's second argument must be an integer, not %s", nameof(ap));
        !           931:                        return;
        !           932:                }
        !           933:                put(1, op);
        !           934:                return;
        !           935:        case O_PAGE:
        !           936:                if (argc != 1) {
        !           937:                        error("page expects one argument");
        !           938:                        return;
        !           939:                }
        !           940:                ap = stkrval(argv[1], NIL , RREQ );
        !           941:                if (ap == NIL)
        !           942:                        return;
        !           943:                if (!text(ap)) {
        !           944:                        error("Argument to page must be a text file, not %s", nameof(ap));
        !           945:                        return;
        !           946:                }
        !           947:                put(1, O_UNIT);
        !           948:                put(1, op);
        !           949:                return;
        !           950: 
        !           951:        case O_PACK:
        !           952:                if (argc != 3) {
        !           953:                        error("pack expects three arguments");
        !           954:                        return;
        !           955:                }
        !           956:                pu = "pack(a,i,z)";
        !           957:                pua = (al = argv)[1];
        !           958:                pui = (al = al[2])[1];
        !           959:                puz = (al = al[2])[1];
        !           960:                goto packunp;
        !           961:        case O_UNPACK:
        !           962:                if (argc != 3) {
        !           963:                        error("unpack expects three arguments");
        !           964:                        return;
        !           965:                }
        !           966:                pu = "unpack(z,a,i)";
        !           967:                puz = (al = argv)[1];
        !           968:                pua = (al = al[2])[1];
        !           969:                pui = (al = al[2])[1];
        !           970: packunp:
        !           971:                ap = stkrval((int *) pui, NLNIL , RREQ );
        !           972:                if (ap == NIL)
        !           973:                        return;
        !           974:                ap = stklval(pua, op == O_PACK ? NOFLAGS : MOD|NOUSE);
        !           975:                if (ap == NIL)
        !           976:                        return;
        !           977:                if (ap->class != ARRAY) {
        !           978:                        error("%s requires a to be an unpacked array, not %s", pu, nameof(ap));
        !           979:                        return;
        !           980:                }
        !           981:                al = (struct nl *) stklval(puz, op == O_UNPACK ? NOFLAGS : MOD|NOUSE);
        !           982:                if (al->class != ARRAY) {
        !           983:                        error("%s requires z to be a packed array, not %s", pu, nameof(ap));
        !           984:                        return;
        !           985:                }
        !           986:                if (al->type == NIL || ap->type == NIL)
        !           987:                        return;
        !           988:                if (al->type != ap->type) {
        !           989:                        error("%s requires a and z to be arrays of the same type", pu, nameof(ap));
        !           990:                        return;
        !           991:                }
        !           992:                k = width(al);
        !           993:                itemwidth = width(ap->type);
        !           994:                ap = ap->chain;
        !           995:                al = al->chain;
        !           996:                if (ap->chain != NIL || al->chain != NIL) {
        !           997:                        error("%s requires a and z to be single dimension arrays", pu);
        !           998:                        return;
        !           999:                }
        !          1000:                if (ap == NIL || al == NIL)
        !          1001:                        return;
        !          1002:                /*
        !          1003:                 * al is the range for z i.e. u..v
        !          1004:                 * ap is the range for a i.e. m..n
        !          1005:                 * i will be n-m+1
        !          1006:                 * j will be v-u+1
        !          1007:                 */
        !          1008:                i = ap->range[1] - ap->range[0] + 1;
        !          1009:                j = al->range[1] - al->range[0] + 1;
        !          1010:                if (i < j) {
        !          1011:                        error("%s cannot have more elements in a (%d) than in z (%d)", pu, j, i);
        !          1012:                        return;
        !          1013:                }
        !          1014:                /*
        !          1015:                 * get n-m-(v-u) and m for the interpreter
        !          1016:                 */
        !          1017:                i -= j;
        !          1018:                j = ap->range[0];
        !          1019:                put(5, op, itemwidth , j, i, k);
        !          1020:                return;
        !          1021:        case 0:
        !          1022:                error("%s is an unimplemented 6400 extension", p->symbol);
        !          1023:                return;
        !          1024: 
        !          1025:        default:
        !          1026:                panic("proc case");
        !          1027:        }
        !          1028: }
        !          1029: #endif OBJ

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.