Annotation of 3BSD/cmd/pi/proc.c, revision 1.1

1.1     ! root        1: /* Copyright (c) 1979 Regents of the University of California */
        !             2: #
        !             3: /*
        !             4:  * pi - Pascal interpreter code translator
        !             5:  *
        !             6:  * Charles Haley, Bill Joy UCB
        !             7:  * Version 1.2 November 1978
        !             8:  */
        !             9: 
        !            10: #include "whoami"
        !            11: #include "0.h"
        !            12: #include "tree.h"
        !            13: #include "opcode.h"
        !            14: 
        !            15: /*
        !            16:  * The following arrays are used to determine which classes may be
        !            17:  * read and written to/from text files.
        !            18:  * They are indexed by the return types from classify.
        !            19:  */
        !            20: #define rdops(x) rdxxxx[(x)-(TFIRST)]
        !            21: #define wrops(x) wrxxxx[(x)-(TFIRST)]
        !            22: 
        !            23: int rdxxxx[] = {
        !            24:        0,              /* -7  file types */
        !            25:        0,              /* -6  record types */
        !            26:        0,              /* -5  array types */
        !            27:        0,              /* -4  scalar types */
        !            28:        0,              /* -3  pointer types */
        !            29:        0,              /* -2  set types */
        !            30:        0,              /* -1  string types */
        !            31:        0,              /*  0  nil - i.e. no type */
        !            32:        0,              /*  1  booleans */
        !            33:        O_READC,        /*  2  character */
        !            34:        O_READ4,        /*  3  integer */
        !            35:        O_READ8         /*  4  real */
        !            36: };
        !            37: 
        !            38: int wrxxxx[] = {
        !            39:        0,              /* -7  file types */
        !            40:        0,              /* -6  record types */
        !            41:        0,              /* -5  array types */
        !            42:        0,              /* -4  scalar types */
        !            43:        0,              /* -3  pointer types */
        !            44:        0,              /* -2  set types */
        !            45:        O_WRITG,        /* -1  string types */
        !            46:        0,              /*  0  nil - i.e. no type */
        !            47:        O_WRITB,        /*  1  booleans */
        !            48:        O_WRITC,        /*  2  character */
        !            49:        O_WRIT4,        /*  3  integer */
        !            50:        O_WRIT8,        /*  4  real */
        !            51: };
        !            52: 
        !            53: /*
        !            54:  * Proc handles procedure calls.
        !            55:  * Non-builtin procedures are "buck-passed" to func (with a flag
        !            56:  * indicating that they are actually procedures.
        !            57:  * builtin procedures are handled here.
        !            58:  */
        !            59: proc(r)
        !            60:        int *r;
        !            61: {
        !            62:        register struct nl *p;
        !            63:        register int *al, op;
        !            64:        struct nl *filetype, *ap;
        !            65:        int argc, *argv, c, two, oct, hex, *file;
        !            66:        int pu;
        !            67:        int *pua, *pui, *puz;
        !            68:        int i, j, k;
        !            69: 
        !            70:        /*
        !            71:         * Verify that the name is
        !            72:         * defined and is that of a
        !            73:         * procedure.
        !            74:         */
        !            75:        p = lookup(r[2]);
        !            76:        if (p == NIL) {
        !            77:                rvlist(r[3]);
        !            78:                return;
        !            79:        }
        !            80:        if (p->class != PROC) {
        !            81:                error("Can't call %s, its %s not a procedure", p->symbol, classes[p->class]);
        !            82:                rvlist(r[3]);
        !            83:                return;
        !            84:        }
        !            85:        argv = r[3];
        !            86: 
        !            87:        /*
        !            88:         * Call handles user defined
        !            89:         * procedures and functions.
        !            90:         */
        !            91:        if (bn != 0) {
        !            92:                call(p, argv, PROC, bn);
        !            93:                return;
        !            94:        }
        !            95: 
        !            96:        /*
        !            97:         * Call to built-in procedure.
        !            98:         * Count the arguments.
        !            99:         */
        !           100:        argc = 0;
        !           101:        for (al = argv; al != NIL; al = al[2])
        !           102:                argc++;
        !           103: 
        !           104:        /*
        !           105:         * Switch on the operator
        !           106:         * associated with the built-in
        !           107:         * procedure in the namelist
        !           108:         */
        !           109:        op = p->value[0] &~ NSTAND;
        !           110:        if (opt('s') && (p->value[0] & NSTAND)) {
        !           111:                standard();
        !           112:                error("%s is a nonstandard procedure", p->symbol);
        !           113:        }
        !           114:        switch (op) {
        !           115: 
        !           116:        case O_NULL:
        !           117:                if (argc != 0)
        !           118:                        error("null takes no arguments");
        !           119:                return;
        !           120: 
        !           121:        case O_FLUSH:
        !           122:                if (argc == 0) {
        !           123:                        put1(O_MESSAGE);
        !           124:                        return;
        !           125:                }
        !           126:                if (argc != 1) {
        !           127:                        error("flush takes at most one argument");
        !           128:                        return;
        !           129:                }
        !           130:                ap = rvalue(argv[1], NIL);
        !           131:                if (ap == NIL)
        !           132:                        return;
        !           133:                if (ap->class != FILET) {
        !           134:                        error("flush's argument must be a file, not %s", nameof(ap));
        !           135:                        return;
        !           136:                }
        !           137:                put1(op);
        !           138:                return;
        !           139: 
        !           140:        case O_MESSAGE:
        !           141:        case O_WRIT2:
        !           142:        case O_WRITLN:
        !           143:                /*
        !           144:                 * Set up default file "output"'s type
        !           145:                 */
        !           146:                file = NIL;
        !           147:                filetype = nl+T1CHAR;
        !           148:                /*
        !           149:                 * Determine the file implied
        !           150:                 * for the write and generate
        !           151:                 * code to make it the active file.
        !           152:                 */
        !           153:                if (op == O_MESSAGE) {
        !           154:                        /*
        !           155:                         * For message, all that matters
        !           156:                         * is that the filetype is
        !           157:                         * a character file.
        !           158:                         * Thus "output" will suit us fine.
        !           159:                         */
        !           160:                        put1(O_MESSAGE);
        !           161:                } else if (argv != NIL && (al = argv[1])[0] != T_WEXP) {
        !           162:                        /*
        !           163:                         * If there is a first argument which has
        !           164:                         * no write widths, then it is potentially
        !           165:                         * a file name.
        !           166:                         */
        !           167:                        codeoff();
        !           168:                        ap = rvalue(argv[1], NIL);
        !           169:                        codeon();
        !           170:                        if (ap == NIL)
        !           171:                                argv = argv[2];
        !           172:                        if (ap != NIL && ap->class == FILET) {
        !           173:                                /*
        !           174:                                 * Got "write(f, ...", make
        !           175:                                 * f the active file, and save
        !           176:                                 * it and its type for use in
        !           177:                                 * processing the rest of the
        !           178:                                 * arguments to write.
        !           179:                                 */
        !           180:                                file = argv[1];
        !           181:                                filetype = ap->type;
        !           182:                                rvalue(argv[1], NIL);
        !           183:                                put1(O_UNIT);
        !           184:                                /*
        !           185:                                 * Skip over the first argument
        !           186:                                 */
        !           187:                                argv = argv[2];
        !           188:                                argc--;
        !           189:                        } else
        !           190:                                /*
        !           191:                                 * Set up for writing on 
        !           192:                                 * standard output.
        !           193:                                 */
        !           194:                                put1(O_UNITOUT);
        !           195:                } else
        !           196:                        put1(O_UNITOUT);
        !           197:                /*
        !           198:                 * Loop and process each
        !           199:                 * of the arguments.
        !           200:                 */
        !           201:                for (; argv != NIL; argv = argv[2]) {
        !           202:                        al = argv[1];
        !           203:                        if (al == NIL)
        !           204:                                continue;
        !           205:                        /*
        !           206:                         * Op will be used to
        !           207:                         * accumulate width information,
        !           208:                         * and two records the fact
        !           209:                         * that we saw two write widths
        !           210:                         */
        !           211:                        op = 0;
        !           212:                        two = 0;
        !           213:                        oct = 0;
        !           214:                        hex = 0;
        !           215:                        if (al[0] == T_WEXP) {
        !           216:                                if (filetype != nl+T1CHAR) {
        !           217:                                        error("Write widths allowed only with text files");
        !           218:                                        continue;
        !           219:                                }
        !           220:                                /*
        !           221:                                 * Handle width expressions.
        !           222:                                 * The basic game here is that width
        !           223:                                 * expressions get evaluated and left
        !           224:                                 * on the stack and their width's get
        !           225:                                 * packed into the high byte of the
        !           226:                                 * affected opcode (subop).
        !           227:                                 */
        !           228:                                if (al[3] == OCT) 
        !           229:                                        oct++;
        !           230:                                else if (al[3] == HEX)
        !           231:                                        hex++;
        !           232:                                else if (al[3] != NIL) {
        !           233:                                        two++;
        !           234:                                        /*
        !           235:                                         * Arrange for the write
        !           236:                                         * opcode that takes two widths
        !           237:                                         */
        !           238:                                        op |= O_WRIT82-O_WRIT8;
        !           239:                                        ap = rvalue(al[3], NIL);
        !           240:                                        if (ap == NIL)
        !           241:                                                continue;
        !           242:                                        if (isnta(ap, "i")) {
        !           243:                                                error("Second write width must be integer, not %s", nameof(ap));
        !           244:                                                continue;
        !           245:                                        }
        !           246:                                        op |= even(width(ap)) << 11;
        !           247:                                }
        !           248:                                if (al[2] != NIL) {
        !           249:                                        ap = rvalue(al[2], NIL);
        !           250:                                        if (ap == NIL)
        !           251:                                                continue;
        !           252:                                        if (isnta(ap, "i")) {
        !           253:                                                error("First write width must be integer, not %s", nameof(ap));
        !           254:                                                continue;
        !           255:                                        }
        !           256:                                        op |= even(width(ap)) << 8;
        !           257:                                }
        !           258:                                al = al[1];
        !           259:                                if (al == NIL)
        !           260:                                        continue;
        !           261:                        }
        !           262:                        if (filetype != nl+T1CHAR) {
        !           263:                                if (oct || hex) {
        !           264:                                        error("Oct/hex allowed only on text files");
        !           265:                                        continue;
        !           266:                                }
        !           267:                                if (op) {
        !           268:                                        error("Write widths allowed only on text files");
        !           269:                                        continue;
        !           270:                                }
        !           271:                                /*
        !           272:                                 * Generalized write, i.e.
        !           273:                                 * to a non-textfile.
        !           274:                                 */
        !           275:                                rvalue(file, NIL);
        !           276:                                put1(O_FNIL);
        !           277:                                /*
        !           278:                                 * file^ := ...
        !           279:                                 */
        !           280:                                ap = rvalue(argv[1], NIL);
        !           281:                                if (ap == NIL)
        !           282:                                        continue;
        !           283:                                if (incompat(ap, filetype, argv[1])) {
        !           284:                                        cerror("Type mismatch in write to non-text file");
        !           285:                                        continue;
        !           286:                                }
        !           287:                                convert(ap, filetype);
        !           288:                                put2(O_AS, width(filetype));
        !           289:                                /*
        !           290:                                 * put(file)
        !           291:                                 */
        !           292:                                put1(O_PUT);
        !           293:                                continue;
        !           294:                        }
        !           295:                        /*
        !           296:                         * Write to a textfile
        !           297:                         *
        !           298:                         * Evaluate the expression
        !           299:                         * to be written.
        !           300:                         */
        !           301:                        ap = rvalue(al, NIL);
        !           302:                        if (ap == NIL)
        !           303:                                continue;
        !           304:                        c = classify(ap);
        !           305:                        if (two && c != TDOUBLE) {
        !           306:                                if (isnta(ap, "i")) {
        !           307:                                        error("Only reals can have two write widths");
        !           308:                                        continue;
        !           309:                                }
        !           310:                                convert(ap, nl+TDOUBLE);
        !           311:                                c = TDOUBLE;
        !           312:                        }
        !           313:                        if (oct || hex) {
        !           314:                                if (opt('s')) {
        !           315:                                        standard();
        !           316:                                        error("Oct and hex are non-standard");
        !           317:                                }
        !           318:                                switch (c) {
        !           319:                                        case TREC:
        !           320:                                        case TARY:
        !           321:                                        case TFILE:
        !           322:                                        case TSTR:
        !           323:                                        case TSET:
        !           324:                                        case TDOUBLE:
        !           325:                                                error("Can't write %ss with oct/hex", clnames[c]);
        !           326:                                                continue;
        !           327:                                }
        !           328:                                put1(op | (oct ? O_WROCT2 : O_WRHEX2) | (width(ap) >> 2));
        !           329:                                continue;
        !           330:                        }
        !           331:                        if (wrops(c) == NIL) {
        !           332:                                error("Can't write %ss to a text file", clnames[c]);
        !           333:                                continue;
        !           334:                        }
        !           335:                        if (c == TINT && width(ap) != 4)
        !           336:                                op |= O_WRIT2;
        !           337:                        else
        !           338:                                op |= wrops(c);
        !           339:                        if (c == TSTR)
        !           340:                                put2(op, width(ap));
        !           341:                        else
        !           342:                                put1(op);
        !           343:                }
        !           344:                /*
        !           345:                 * Done with arguments.
        !           346:                 * Handle writeln and
        !           347:                 * insufficent number of args.
        !           348:                 */
        !           349:                switch (p->value[0] &~ NSTAND) {
        !           350:                        case O_WRIT2:
        !           351:                                if (argc == 0)
        !           352:                                        error("Write requires an argument");
        !           353:                                break;
        !           354:                        case O_MESSAGE:
        !           355:                                if (argc == 0)
        !           356:                                        error("Message requires an argument");
        !           357:                        case O_WRITLN:
        !           358:                                if (filetype != nl+T1CHAR)
        !           359:                                        error("Can't 'writeln' a non text file");
        !           360:                                put1(O_WRITLN);
        !           361:                                break;
        !           362:                }
        !           363:                return;
        !           364: 
        !           365:        case O_READ4:
        !           366:        case O_READLN:
        !           367:                /*
        !           368:                 * Set up default
        !           369:                 * file "input".
        !           370:                 */
        !           371:                file = NIL;
        !           372:                filetype = nl+T1CHAR;
        !           373:                /*
        !           374:                 * Determine the file implied
        !           375:                 * for the read and generate
        !           376:                 * code to make it the active file.
        !           377:                 */
        !           378:                if (argv != NIL) {
        !           379:                        codeoff();
        !           380:                        ap = rvalue(argv[1], NIL);
        !           381:                        codeon();
        !           382:                        if (ap == NIL)
        !           383:                                argv = argv[2];
        !           384:                        if (ap != NIL && ap->class == FILET) {
        !           385:                                /*
        !           386:                                 * Got "read(f, ...", make
        !           387:                                 * f the active file, and save
        !           388:                                 * it and its type for use in
        !           389:                                 * processing the rest of the
        !           390:                                 * arguments to read.
        !           391:                                 */
        !           392:                                file = argv[1];
        !           393:                                filetype = ap->type;
        !           394:                                rvalue(argv[1], NIL);
        !           395:                                put1(O_UNIT);
        !           396:                                argv = argv[2];
        !           397:                                argc--;
        !           398:                        } else {
        !           399:                                /*
        !           400:                                 * Default is read from
        !           401:                                 * standard input.
        !           402:                                 */
        !           403:                                put1(O_UNITINP);
        !           404:                                input->nl_flags |= NUSED;
        !           405:                        }
        !           406:                } else {
        !           407:                        put1(O_UNITINP);
        !           408:                        input->nl_flags |= NUSED;
        !           409:                }
        !           410:                /*
        !           411:                 * Loop and process each
        !           412:                 * of the arguments.
        !           413:                 */
        !           414:                for (; argv != NIL; argv = argv[2]) {
        !           415:                        /*
        !           416:                         * Get the address of the target
        !           417:                         * on the stack.
        !           418:                         */
        !           419:                        al = argv[1];
        !           420:                        if (al == NIL)
        !           421:                                continue;
        !           422:                        if (al[0] != T_VAR) {
        !           423:                                error("Arguments to %s must be variables, not expressions", p->symbol);
        !           424:                                continue;
        !           425:                        }
        !           426:                        ap = lvalue(al, MOD|ASGN|NOUSE);
        !           427:                        if (ap == NIL)
        !           428:                                continue;
        !           429:                        if (filetype != nl+T1CHAR) {
        !           430:                                /*
        !           431:                                 * Generalized read, i.e.
        !           432:                                 * from a non-textfile.
        !           433:                                 */
        !           434:                                if (incompat(filetype, ap, NIL)) {
        !           435:                                        error("Type mismatch in read from non-text file");
        !           436:                                        continue;
        !           437:                                }
        !           438:                                /*
        !           439:                                 * var := file ^;
        !           440:                                 */
        !           441:                                if (file != NIL)
        !           442:                                        rvalue(file, NIL);
        !           443:                                else /* Magic */
        !           444:                                        put2(O_RV2, input->value[0]);
        !           445:                                put1(O_FNIL);
        !           446:                                put2(O_IND, width(filetype));
        !           447:                                convert(filetype, ap);
        !           448:                                if (isa(ap, "bsci"))
        !           449:                                        rangechk(ap, ap);
        !           450:                                put2(O_AS, width(ap));
        !           451:                                /*
        !           452:                                 * get(file);
        !           453:                                 */
        !           454:                                put1(O_GET);
        !           455:                                continue;
        !           456:                        }
        !           457:                        c = classify(ap);
        !           458:                        op = rdops(c);
        !           459:                        if (op == NIL) {
        !           460:                                error("Can't read %ss from a text file", clnames[c]);
        !           461:                                continue;
        !           462:                        }
        !           463:                        put1(op);
        !           464:                        /*
        !           465:                         * Data read is on the stack.
        !           466:                         * Assign it.
        !           467:                         */
        !           468:                        if (op != O_READ8)
        !           469:                                rangechk(ap, op == O_READC ? ap : nl+T4INT);
        !           470:                        gen(O_AS2, O_AS2, width(ap),
        !           471:                                op == O_READ8 ? 8 : op == O_READ4 ? 4 : 2);
        !           472:                }
        !           473:                /*
        !           474:                 * Done with arguments.
        !           475:                 * Handle readln and
        !           476:                 * insufficient number of args.
        !           477:                 */
        !           478:                if (p->value[0] == O_READLN) {
        !           479:                        if (filetype != nl+T1CHAR)
        !           480:                                error("Can't 'readln' a non text file");
        !           481:                        put1(O_READLN);
        !           482:                }
        !           483:                else if (argc == 0)
        !           484:                        error("read requires an argument");
        !           485:                return;
        !           486: 
        !           487:        case O_GET:
        !           488:        case O_PUT:
        !           489:                if (argc != 1) {
        !           490:                        error("%s expects one argument", p->symbol);
        !           491:                        return;
        !           492:                }
        !           493:                ap = rvalue(argv[1], NIL);
        !           494:                if (ap == NIL)
        !           495:                        return;
        !           496:                if (ap->class != FILET) {
        !           497:                        error("Argument to %s must be a file, not %s", p->symbol, nameof(ap));
        !           498:                        return;
        !           499:                }
        !           500:                put1(O_UNIT);
        !           501:                put1(op);
        !           502:                return;
        !           503: 
        !           504:        case O_RESET:
        !           505:        case O_REWRITE:
        !           506:                if (argc == 0 || argc > 2) {
        !           507:                        error("%s expects one or two arguments", p->symbol);
        !           508:                        return;
        !           509:                }
        !           510:                if (opt('s') && argc == 2) {
        !           511:                        standard();
        !           512:                        error("Two argument forms of reset and rewrite are non-standard");
        !           513:                }
        !           514:                ap = lvalue(argv[1], MOD|NOUSE);
        !           515:                if (ap == NIL)
        !           516:                        return;
        !           517:                if (ap->class != FILET) {
        !           518:                        error("First argument to %s must be a file, not %s", p->symbol, nameof(ap));
        !           519:                        return;
        !           520:                }
        !           521:                if (argc == 2) {
        !           522:                        /*
        !           523:                         * Optional second argument
        !           524:                         * is a string name of a
        !           525:                         * UNIX (R) file to be associated.
        !           526:                         */
        !           527:                        al = argv[2];
        !           528:                        al = rvalue(al[1], NIL);
        !           529:                        if (al == NIL)
        !           530:                                return;
        !           531:                        if (classify(al) != TSTR) {
        !           532:                                error("Second argument to %s must be a string, not %s", p->symbol, nameof(al));
        !           533:                                return;
        !           534:                        }
        !           535:                        c = width(al);
        !           536:                } else
        !           537:                        c = 0;
        !           538:                if (c > 127) {
        !           539:                        error("File name too long");
        !           540:                        return;
        !           541:                }
        !           542:                put2(op | c << 8, text(ap) ? 0: width(ap->type));
        !           543:                return;
        !           544: 
        !           545:        case O_NEW:
        !           546:        case O_DISPOSE:
        !           547:                if (argc == 0) {
        !           548:                        error("%s expects at least one argument", p->symbol);
        !           549:                        return;
        !           550:                }
        !           551:                ap = lvalue(argv[1], MOD|NOUSE);
        !           552:                if (ap == NIL)
        !           553:                        return;
        !           554:                if (ap->class != PTR) {
        !           555:                        error("(First) argument to %s must be a pointer, not %s", p->symbol, nameof(ap));
        !           556:                        return;
        !           557:                }
        !           558:                ap = ap->type;
        !           559:                if (ap == NIL)
        !           560:                        return;
        !           561:                argv = argv[2];
        !           562:                if (argv != NIL) {
        !           563:                        if (ap->class != RECORD) {
        !           564:                                error("Record required when specifying variant tags");
        !           565:                                return;
        !           566:                        }
        !           567:                        for (; argv != NIL; argv = argv[2]) {
        !           568:                                if (ap->ptr[NL_VARNT] == NIL) {
        !           569:                                        error("Too many tag fields");
        !           570:                                        return;
        !           571:                                }
        !           572:                                if (!isconst(argv[1])) {
        !           573:                                        error("Second and successive arguments to %s must be constants", p->symbol);
        !           574:                                        return;
        !           575:                                }
        !           576:                                gconst(argv[1]);
        !           577:                                if (con.ctype == NIL)
        !           578:                                        return;
        !           579:                                if (incompat(con.ctype, (ap->ptr[NL_TAG])->type)) {
        !           580:                                        cerror("Specified tag constant type clashed with variant case selector type");
        !           581:                                        return;
        !           582:                                }
        !           583:                                for (ap = ap->ptr[NL_VARNT]; ap != NIL; ap = ap->chain)
        !           584:                                        if (ap->range[0] == con.crval)
        !           585:                                                break;
        !           586:                                if (ap == NIL) {
        !           587:                                        error("No variant case label value equals specified constant value");
        !           588:                                        return;
        !           589:                                }
        !           590:                                ap = ap->ptr[NL_VTOREC];
        !           591:                        }
        !           592:                }
        !           593:                put2(op, width(ap));
        !           594:                return;
        !           595: 
        !           596:        case O_DATE:
        !           597:        case O_TIME:
        !           598:                if (argc != 1) {
        !           599:                        error("%s expects one argument", p->symbol);
        !           600:                        return;
        !           601:                }
        !           602:                ap = lvalue(argv[1], MOD|NOUSE);
        !           603:                if (ap == NIL)
        !           604:                        return;
        !           605:                if (classify(ap) != TSTR || width(ap) != 10) {
        !           606:                        error("Argument to %s must be a alfa, not %s", p->symbol, nameof(ap));
        !           607:                        return;
        !           608:                }
        !           609:                put1(op);
        !           610:                return;
        !           611: 
        !           612:        case O_HALT:
        !           613:                if (argc != 0) {
        !           614:                        error("halt takes no arguments");
        !           615:                        return;
        !           616:                }
        !           617:                put1(op);
        !           618:                noreach = 1;
        !           619:                return;
        !           620: 
        !           621:        case O_ARGV:
        !           622:                if (argc != 2) {
        !           623:                        error("argv takes two arguments");
        !           624:                        return;
        !           625:                }
        !           626:                ap = rvalue(argv[1], NIL);
        !           627:                if (ap == NIL)
        !           628:                        return;
        !           629:                if (isnta(ap, "i")) {
        !           630:                        error("argv's first argument must be an integer, not %s", nameof(ap));
        !           631:                        return;
        !           632:                }
        !           633:                convert(ap, nl+T2INT);
        !           634:                al = argv[2];
        !           635:                ap = lvalue(al[1], MOD|NOUSE);
        !           636:                if (ap == NIL)
        !           637:                        return;
        !           638:                if (classify(ap) != TSTR) {
        !           639:                        error("argv's second argument must be a string, not %s", nameof(ap));
        !           640:                        return;
        !           641:                }
        !           642:                put2(op, width(ap));
        !           643:                return;
        !           644: 
        !           645:        case O_STLIM:
        !           646:                if (argc != 1) {
        !           647:                        error("stlimit requires one argument");
        !           648:                        return;
        !           649:                }
        !           650:                ap = rvalue(argv[1], NIL);
        !           651:                if (ap == NIL)
        !           652:                        return;
        !           653:                if (isnta(ap, "i")) {
        !           654:                        error("stlimit's argument must be an integer, not %s", nameof(ap));
        !           655:                        return;
        !           656:                }
        !           657:                if (width(ap) != 4)
        !           658:                        put1(O_STOI);
        !           659:                put1(op);
        !           660:                return;
        !           661: 
        !           662:        case O_REMOVE:
        !           663:                if (argc != 1) {
        !           664:                        error("remove expects one argument");
        !           665:                        return;
        !           666:                }
        !           667:                ap = rvalue(argv[1], NIL);
        !           668:                if (ap == NIL)
        !           669:                        return;
        !           670:                if (classify(ap) != TSTR) {
        !           671:                        error("remove's argument must be a string, not %s", nameof(ap));
        !           672:                        return;
        !           673:                }
        !           674:                put2(op, width(ap));
        !           675:                return;
        !           676: 
        !           677:        case O_LLIMIT:
        !           678:                if (argc != 2) {
        !           679:                        error("linelimit expects two arguments");
        !           680:                        return;
        !           681:                }
        !           682:                ap = lvalue(argv[1], NOMOD|NOUSE);
        !           683:                if (ap == NIL)
        !           684:                        return;
        !           685:                if (!text(ap)) {
        !           686:                        error("linelimit's first argument must be a text file, not %s", nameof(ap));
        !           687:                        return;
        !           688:                }
        !           689:                al = argv[2];
        !           690:                ap = rvalue(al[1], NIL);
        !           691:                if (ap == NIL)
        !           692:                        return;
        !           693:                if (isnta(ap, "i")) {
        !           694:                        error("linelimit's second argument must be an integer, not %s", nameof(ap));
        !           695:                        return;
        !           696:                }
        !           697:                convert(ap, nl+T4INT);
        !           698:                put1(op);
        !           699:                return;
        !           700:        case O_PAGE:
        !           701:                if (argc != 1) {
        !           702:                        error("page expects one argument");
        !           703:                        return;
        !           704:                }
        !           705:                ap = rvalue(argv[1], NIL);
        !           706:                if (ap == NIL)
        !           707:                        return;
        !           708:                if (!text(ap)) {
        !           709:                        error("Argument to page must be a text file, not %s", nameof(ap));
        !           710:                        return;
        !           711:                }
        !           712:                put1(O_UNIT);
        !           713:                put1(op);
        !           714:                return;
        !           715: 
        !           716:        case O_PACK:
        !           717:                if (argc != 3) {
        !           718:                        error("pack expects three arguments");
        !           719:                        return;
        !           720:                }
        !           721:                pu = "pack(a,i,z)";
        !           722:                pua = (al = argv)[1];
        !           723:                pui = (al = al[2])[1];
        !           724:                puz = (al = al[2])[1];
        !           725:                goto packunp;
        !           726:        case O_UNPACK:
        !           727:                if (argc != 3) {
        !           728:                        error("unpack expects three arguments");
        !           729:                        return;
        !           730:                }
        !           731:                pu = "unpack(z,a,i)";
        !           732:                puz = (al = argv)[1];
        !           733:                pua = (al = al[2])[1];
        !           734:                pui = (al = al[2])[1];
        !           735: packunp:
        !           736:                ap = rvalue((int *) pui, NLNIL);
        !           737:                if (ap == NIL)
        !           738:                        return;
        !           739:                if (width(ap) == 4)
        !           740:                        put1(O_ITOS);
        !           741:                ap = lvalue(pua, op == O_PACK ? NOMOD : MOD|NOUSE);
        !           742:                if (ap == NIL)
        !           743:                        return;
        !           744:                if (ap->class != ARRAY) {
        !           745:                        error("%s requires a to be an unpacked array, not %s", pu, nameof(ap));
        !           746:                        return;
        !           747:                }
        !           748:                al = (struct nl *) lvalue(puz, op == O_UNPACK ? NOMOD : MOD|NOUSE);
        !           749:                if (al->class != ARRAY) {
        !           750:                        error("%s requires z to be a packed array, not %s", pu, nameof(ap));
        !           751:                        return;
        !           752:                }
        !           753:                if (al->type == NIL || ap->type == NIL)
        !           754:                        return;
        !           755:                if (al->type != ap->type) {
        !           756:                        error("%s requires a and z to be arrays of the same type", pu, nameof(ap));
        !           757:                        return;
        !           758:                }
        !           759:                k = width(al);
        !           760:                ap = ap->chain;
        !           761:                al = al->chain;
        !           762:                if (ap->chain != NIL || al->chain != NIL) {
        !           763:                        error("%s requires a and z to be single dimension arrays", pu);
        !           764:                        return;
        !           765:                }
        !           766:                if (ap == NIL || al == NIL)
        !           767:                        return;
        !           768:                /*
        !           769:                 * al is the range for z i.e. u..v
        !           770:                 * ap is the range for a i.e. m..n
        !           771:                 * i will be n-m+1
        !           772:                 * j will be v-u+1
        !           773:                 */
        !           774:                i = ap->range[1] - ap->range[0] + 1;
        !           775:                j = al->range[1] - al->range[0] + 1;
        !           776:                if (i < j) {
        !           777:                        error("%s cannot have more elements in a (%d) than in z (%d)", pu, j, i);
        !           778:                        return;
        !           779:                }
        !           780:                /*
        !           781:                 * get n-m-(v-u) and m for the interpreter
        !           782:                 */
        !           783:                i -= j;
        !           784:                j = ap->range[0];
        !           785:                put(5, op, width(ap), j, i, k);
        !           786:                return;
        !           787:        case 0:
        !           788:                error("%s is an unimplemented 6400 extension", p->symbol);
        !           789:                return;
        !           790: 
        !           791:        default:
        !           792:                panic("proc case");
        !           793:        }
        !           794: }

unix.superglobalmegacorp.com

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