Annotation of 43BSD/contrib/apl/src/ai.c, revision 1.1.1.1

1.1       root        1: static char Sccsid[] = "ai.c @(#)ai.c  1.2     10/1/82 Berkeley ";
                      2: #include <signal.h>
                      3: #include "apl.h"
                      4: 
                      5: char *bad_fn  = "apl.badfn";
                      6: int prolgerr;          /* Flag -- set if bad fetch in prologue */
                      7: 
                      8: /*
                      9:  * funedit -- edit a file and read it in.
                     10:  *
                     11:  * If the arg to funedit is non-zero, it is used as a 
                     12:  * pointer to the file name to be used.  If it is zero,
                     13:  * the namep of the function is used for the file name.
                     14:  */
                     15: funedit(fname, editor)
                     16: char *fname;
                     17: {
                     18:        register struct item *p;
                     19:        register f, (*a)();
                     20:        char *c;
                     21:        extern edmagic;
                     22: 
                     23:        p = sp[-1];
                     24:        if(p->type != LV)
                     25:                error("fed B");
                     26:        sichk(p);
                     27:        if(fname == 0)
                     28:                fname = ((struct nlist *)p)->namep;
                     29:        a = signal(SIGINT, SIG_IGN);
                     30:        f = FORKF(1);
                     31:        if(f == 0) {
                     32:                for(f=3; f<7; f++)
                     33:                        close(f);
                     34:                c = (editor == DEL ? "/usr/bin/apldel" : "/usr/local/xed");
                     35:                execl(c+9, c+9, fname, "-f", apl_term ? "-A":"-a", "-p", edmagic ? "-r":0, 0);
                     36:                execl(c+4, c+9, fname, "-f", apl_term ? "-A":"-a", "-p", edmagic ? "-r":0, 0);
                     37:                execl(c, c+9, fname, "-f", apl_term ? "-A":"-a", "-p", edmagic ? "-r":0, 0);
                     38:                printf("cannot find the editor!\n");
                     39:                exit(1);
                     40:        }
                     41:        if(f == -1)
                     42:                error("try again");
                     43:        while(wait(0) != f)
                     44:                ;
                     45:        signal(SIGINT, a);
                     46: 
                     47:        /* Read function into workspace.  If "funread" (which calls
                     48:         * "fundef") returns 0, an error occurred in processing the
                     49:         * header (line 0).  If this happened with "editf" or "del",
                     50:         * save the bad function in the file "bad_fn".
                     51:         */
                     52: 
                     53:        if (funread(fname) == 0 && fname == scr_file){
                     54:                unlink(bad_fn);
                     55:                if (badfnsv(fname))
                     56:                        printf("function saved in %s\n", bad_fn);
                     57:        }
                     58: }
                     59: 
                     60: 
                     61: funread(fname)
                     62: char *fname;
                     63: {
                     64:        register struct item *p;
                     65:        register f, pid;
                     66: 
                     67:        p = sp[-1];
                     68:        sp--;
                     69:        if(p->type != LV)
                     70:                error("fnl B");
                     71:        if(fname == 0)
                     72:                fname = ((struct nlist *)p)->namep;
                     73:        f = opn(fname, 0);
                     74:        return(fundef(f));
                     75: }
                     76: 
                     77: funwrite(fname)
                     78: char *fname;
                     79: {
                     80:        register struct nlist *n;
                     81:        register i, cnt;
                     82:        int fd1, fd2;
                     83:        char buf[512];
                     84: 
                     85:        n = (struct nlist *)sp[-1];
                     86:        sp--;
                     87:        if(n->type != LV)
                     88:                error("fnwrite B");
                     89:        if(fname ==0)
                     90:                fname = n->namep;
                     91:        fd1 = opn(fname, 0644);
                     92:        switch(n->use){
                     93:        default:
                     94:                CLOSEF(fd1);
                     95:                error("fnwrite T");
                     96: 
                     97:        case 0:                 /* undefined fn */
                     98:                printf("\t[new fn]\n");
                     99:                break;          /* empty file already created -- do nothing */
                    100: 
                    101:        case NF:
                    102:        case MF:
                    103:        case DF:
                    104:                fd2 = DUPF(wfile);
                    105:                SEEKF(fd2, (long)n->label, 0);
                    106:                do {
                    107:                        cnt = READF(fd2, buf, 512);
                    108:                        if(cnt <= 0)
                    109:                                error("fnwrite eof");
                    110:                        for(i=0; i<cnt; i++)
                    111:                                if(buf[i] == 0)
                    112:                                        break;
                    113:                        WRITEF(fd1, buf, i);
                    114:                } while(i == 512);
                    115:                CLOSEF(fd2);
                    116:                break;
                    117:        }
                    118:        CLOSEF(fd1);
                    119: }
                    120: 
                    121: fundef(f)
                    122: {
                    123:        register a, c;
                    124:        struct nlist *np;
                    125:        char b[512];
                    126: 
                    127:        ifile = f;
                    128:        a = rline(0);
                    129:        if(a == 0)
                    130:                error("fnd eof");
                    131:        c = compile(a, 2);
                    132:        free(a);
                    133:        if(c == 0)
                    134:                goto out;
                    135:        copy(IN, c+1, &np, 1);
                    136:        sichk(np);
                    137:        erase(np);
                    138:        np->use = ((struct chrstrct *)c)->c[0];
                    139:        np->label = SEEKF(wfile, 0L, 2);
                    140:        SEEKF(ifile, 0L, 0);
                    141:        while((a=READF(ifile, b, 512)) > 0)
                    142:                WRITEF(wfile, b, a);
                    143:        WRITEF(wfile, "", 1);
                    144: out:
                    145:        CLOSEF(ifile);
                    146:        ifile = 0;
                    147:        return(c);
                    148: }
                    149: 
                    150: data lnumb;
                    151: char *labcpp,*labcpe;
                    152: 
                    153: funcomp(np)
                    154: struct nlist *np;
                    155: {
                    156:        register char *a, *c;
                    157:        register  *p;
                    158:        int i, err, size;
                    159:        char labp[MAXLAB*20], labe[MAXLAB*4];
                    160: 
                    161:        ifile = DUPF(wfile);
                    162:        SEEKF(ifile, (long)np->label, 0);
                    163:        size = 0;
                    164:        err = 0;
                    165: 
                    166:        labgen = 0;
                    167: pass1:
                    168:        a = rline(0);
                    169:        if(a == 0) {
                    170:                if(err)
                    171:                        goto out;
                    172:                p = (int *)alloc((size+2)*SINT);
                    173:                *p = size;
                    174:                size = 0;
                    175:                SEEKF(ifile, (long)np->label, 0);
                    176:                err++;
                    177:                labcpp = labp;
                    178:                labcpe = labe;
                    179:                labgen = 1;
                    180:                goto pass2;
                    181:        }
                    182:        c = compile(a, size==0? 3: 5);
                    183:        size++;
                    184:        free(a);
                    185:        if(c == 0) {
                    186:                err++;
                    187:                goto pass1;
                    188:        }
                    189:        free(c);
                    190:        goto pass1;
                    191: 
                    192: pass2:
                    193:        a = rline(0);
                    194:        if(a == 0)
                    195:                goto pass3;
                    196:        lnumb = size;
                    197:        c = compile(a, size==0? 3: 5);
                    198:        size++;
                    199:        free(a);
                    200:        if(c == 0)
                    201:                goto out;
                    202:        p[size] = c;
                    203:        goto pass2;
                    204: 
                    205: pass3:
                    206:        labgen = 0;
                    207:        SEEKF(ifile, (long)np->label, 0);
                    208:        a = rline(0);
                    209:        if(a == 0){
                    210:                err++;
                    211:                goto out;
                    212:        }
                    213:        c = compile(a, 4);
                    214:        free(a);
                    215:        if(c == 0)
                    216:                goto out;
                    217:        if(labcpp != labp){
                    218:                reverse(labe);
                    219:                p[size+1] = catcode(labe, c);
                    220:                free(c);
                    221:                /*
                    222:                /*              *** KLUDGE ***
                    223:                /*
                    224:                /* due to the "line-at-a-time" nature of the parser,
                    225:                /* we have to screw around with the compiled strings.
                    226:                /*
                    227:                /* At this point, we have:
                    228:                /*
                    229:                /* fn-prologue (p[1]):          <AUTOs and ARGs>, ELID, EOF
                    230:                /* label-prologue (labp):       <AUTOs and LABELs>, EOF
                    231:                /* 
                    232:                /* and we want to produce:
                    233:                /* 
                    234:                /* fn-prologue (p[1]):  <AUTOs and ARGs>,<AUTOs and LABELs>,  ELID, EOF.
                    235:                 */
                    236:                a = csize(p[1]) - 1;
                    237:                c = csize(labp) - 1;
                    238:                /*
                    239:                 * if there is an ELID at the end of the fn-prologue,
                    240:                 * move it to  the end of the label-prologue.
                    241:                 */
                    242:                if (p[1]->c[(int)a-1] == ELID){
                    243:                        p[1]->c[(int)a-1] = EOF;
                    244:                        labp[(int)c] = ELID;
                    245:                        labp[(int)c+1] = EOF;
                    246:                } else
                    247:                        error("elid B");
                    248:                /* *** END KLUDGE *** */
                    249:                a = p[1];
                    250:                p[1] = catcode(a,labp);
                    251:                free(a);
                    252:        } else
                    253:                p[size+1] = c;
                    254:        if(debug) {
                    255:                dump(p[1], 1);
                    256:                dump(p[size+1], 1);
                    257:        }
                    258:        np->itemp = (struct item *)p;
                    259:        err = 0;
                    260: 
                    261: out:
                    262:        CLOSEF(ifile);
                    263:        ifile = 0;
                    264:        if(err)
                    265:                error("syntax");
                    266: }
                    267: 
                    268: ex_fun()
                    269: {
                    270:        struct nlist *np;
                    271:        register *p, s;
                    272:        struct si si;
                    273: 
                    274:        pcp += copy(IN, pcp, &np, 1);
                    275:        if (np->use < NF || np->use > DF) {
                    276:                printf("%s: ", np->namep);
                    277:                error("not a fn");
                    278:        }
                    279:        if(np->itemp == 0)
                    280:                funcomp(np);
                    281:        p = (int *)np->itemp;
                    282:        /* setup new state indicator */
                    283:        si.sip = gsip;
                    284:        gsip = &si;
                    285:        si.np = np;
                    286:        si.oldsp = 0;           /* we can add a more complicated version, later */
                    287:        si.oldpcp = pcp;
                    288:        si.funlc = 0;
                    289:        si.suspended = 0;
                    290:        prolgerr = 0;           /* Reset error flag */
                    291:        s = *p;
                    292:        checksp();
                    293:        if(funtrace)
                    294:                printf("\ntrace: fn %s entered: ", np->namep);
                    295:        if (setjmp(si.env))
                    296:                goto reenter;
                    297:        while(1){
                    298:                si.funlc++;
                    299:                if(funtrace)
                    300:                        printf("\ntrace: fn %s[%d]: ", np->namep, si.funlc-1);
                    301:                execute(p[si.funlc]);
                    302:                if(si.funlc == 1){
                    303:                        si.oldsp = sp;
                    304:                        if (prolgerr)
                    305:                                error("");
                    306:                }
                    307:                if(intflg)
                    308:                        error("I");
                    309:        reenter:
                    310:                if(si.funlc <= 0 || si.funlc >= s) {
                    311:                        si.funlc = 1;   /* for pretty traceback */
                    312:                        if(funtrace)
                    313:                                printf("\ntrace: fn %s exits ", np->namep);
                    314:                        execute(p[s+1]);
                    315:                        /* restore state indicator to previous state */
                    316:                        gsip = si.sip;
                    317:                        pcp = si.oldpcp;
                    318:                        return;
                    319:                }
                    320:                pop();
                    321:        }
                    322: }
                    323: 
                    324: ex_arg1()
                    325: {
                    326:        register struct item *p;
                    327:        struct nlist *np;
                    328: 
                    329:        pcp += copy(IN, pcp, &np, 1);
                    330:        p = fetch1();
                    331:        sp[-1] = np->itemp;
                    332:        np->itemp = p;
                    333:        np->use = DA;
                    334: }
                    335: 
                    336: ex_arg2()
                    337: {
                    338:        register struct item *p1, *p2;
                    339:        struct nlist *np1, *np2;
                    340: 
                    341:        pcp += copy(IN, pcp, &np2, 1);  /* get first argument's name */
                    342:        pcp++;                          /* skip over ARG1 */
                    343:        pcp += copy(IN, pcp, &np1, 1);  /* get second arg's name */
                    344:        p1 = fetch1();                  /* get first expr to be bound to arg */
                    345:        p2 = fetch(sp[-2]);             /* get second one */
                    346:        sp[-1] = np1->itemp;            /* save old value of name on stack */
                    347:        sp[-2] = np2->itemp;            /* save second */
                    348:        np1->itemp = p1;                /* new arg1 binding */
                    349:        np2->itemp = p2;                /* ditto arg2 */
                    350:        np1->use = DA;                  /* release safety catch */
                    351:        np2->use = DA;
                    352: }
                    353: 
                    354: ex_auto()
                    355: {
                    356:        struct nlist *np;
                    357: 
                    358:        pcp += copy(IN, pcp, &np, 1);
                    359:        checksp();
                    360:        *sp++ = np->itemp;
                    361:        np->itemp = 0;
                    362:        np->use = 0;
                    363: }
                    364: 
                    365: ex_rest()
                    366: {
                    367:        register struct item *p;
                    368:        struct nlist *np;
                    369: 
                    370:        p = sp[-1];
                    371:        /*
                    372:         * the following is commented out because
                    373:         * of an obscure bug in the parser, which is
                    374:         * too difficult to correct right now.
                    375:         * the bug is related to the way the
                    376:         * "fn epilog" is compiled.  To accomodate labels,
                    377:         * it was kludged up to have the label restoration
                    378:         * code added after the entire fn was parsed.  A problem
                    379:         * is that the generated code is like:
                    380:         *
                    381:         * "rest-lab1 rest-lab2 eol rval-result rest-arg1 ..."
                    382:         *
                    383:         * the "eol rval-result" pops off the previous result, and
                    384:         * puts a "fetched" version of the returned value (result)
                    385:         * onto the stack.  The bug is that the "eol rval." should
                    386:         * be output at the beginning of the fn epilog.
                    387:         * The following two lines used to be a simple
                    388:         * "p = fetch(p)", which is used to disallow
                    389:         * a fn to return a LV, (by fetching it, it gets
                    390:         * converted to a RVAL.)  Since we later added
                    391:         * code which returned stuff which could not be
                    392:         * fetched (the DU, dummy datum, for example),
                    393:         * this thing had to be eliminated.  An earlier
                    394:         * version only fetched LV's, but that was eliminated
                    395:         * by adding the "RVAL" operator.  The test below
                    396:         * was made a botch, because no LV's should ever be
                    397:         * passed back.  However, for this to be true, the
                    398:         * "eol" should be executed first, so that any possible
                    399:         * LV's left around by the last line executed are
                    400:         * discarded.  Since we have some "rest"s in the epilog
                    401:         * before the eol, the following test fails.
                    402:         * I can't think of why it won't work properly as it
                    403:         * is, but if I had the time, I'd fix it properly.
                    404:         *      --jjb
                    405:         */
                    406: /*     if(p->type == LV)
                    407:                error("rest B");        */
                    408:        pcp += copy(IN, pcp, &np, 1);
                    409:        erase(np);
                    410:        np->itemp = sp[-2];
                    411:        np->use = 0;
                    412:        if(np->itemp)
                    413:                np->use = DA;
                    414:        sp--;
                    415:        sp[-1] = p;
                    416: }
                    417: 
                    418: ex_br0()
                    419: {
                    420: 
                    421:        gsip->funlc = 0;
                    422:        ex_elid();
                    423: }
                    424: 
                    425: ex_br()
                    426: {
                    427:        register struct item *p;
                    428: 
                    429:        p = fetch1();
                    430:        if(p->size == 0)
                    431:                return;
                    432:        gsip->funlc = fix(getdat(p));
                    433: }
                    434: /*
                    435:  * immediate niladic branch -- reset SI
                    436:  */
                    437: ex_ibr0()
                    438: {
                    439:        register struct si *s;
                    440:        register *p;
                    441: 
                    442:        s = gsip;
                    443:        if(s == 0)
                    444:                error("no suspended fn");
                    445:        if(s->suspended == 0)
                    446:                error("imm } B1");
                    447:        gsip->suspended = 0;
                    448:        while((s = gsip) && s->suspended == 0){
                    449:                if(s->oldsp == 0 || sp < s->oldsp)
                    450:                        error("imm } B2");
                    451:                while(sp > s->oldsp){
                    452:                        pop();
                    453:                }
                    454:                pop();          /* pop off possibly bad previous result */
                    455:                ex_nilret();    /* and stick on some dummy datum */
                    456:                p = (int *)s->np->itemp;
                    457:                execute(p[*p + 1]);
                    458:                gsip = s->sip;
                    459:        }
                    460:        if(gsip == 0)
                    461:                while(sp > stack)
                    462:                        pop();
                    463: }
                    464: 
                    465: /*
                    466:  * monadic immediate branch -- resume fn at specific line
                    467:  */
                    468: 
                    469: ex_ibr()
                    470: {
                    471:        register struct si *s;
                    472:        if((s = gsip) == 0)
                    473:                error("no suspended fn");
                    474:        ex_br();
                    475:        if(s->oldsp == 0 || sp < s->oldsp)
                    476:                error("imm }n B");
                    477:        while(sp > s->oldsp){
                    478:                pop();
                    479:        }
                    480:        pop();          /* pop off possibly bad previous result */
                    481:        ex_nilret();    /* and stick on some dummy datum */
                    482:        longjmp(s->env);        /* warp out */
                    483: }
                    484: 
                    485: ex_fdef()
                    486: {
                    487:        register struct item *p;
                    488:        register char *p1, *p2;
                    489:        struct nlist *np;
                    490:        char b[512];
                    491:        int i, dim0, dim1;
                    492: 
                    493:        p = fetch1();
                    494:        if((p->rank != 2 && p->rank != 1) || p->type != CH)
                    495:                error("Lfx D");
                    496: 
                    497: 
                    498:        /* The following code has been commented out as a
                    499:         * test of slight modifications to the compiler.
                    500:         * Before this change, it was impossible to use "Lfx"
                    501:         * from inside an APL function, for it might damage
                    502:         * an existing function by the same name.  The compiler
                    503:         * now checks when processing function headers to see
                    504:         * if the function is suspended by calling "sichk", which
                    505:         * will generate an error if so.  Hopefully this will now
                    506:         * allow "Lfx" to be used freely without disastrous side-
                    507:         * effects.
                    508:         */
                    509: 
                    510: /*     if(gsip)
                    511:                error("si damage -- type ')reset'");    */
                    512: 
                    513:        dim0 = p->dim[0];
                    514:        dim1 = p->dim[1];
                    515:        if(p->rank == 1)
                    516:                dim1 = dim0;
                    517:        copy(CH, p->datap, b, dim1);
                    518:        b[dim1] = '\n';
                    519: 
                    520:        p2 = compile(b, 2);
                    521:        if(p2 != 0){
                    522:                copy(IN, p2+1, &np, 1);
                    523:                erase(np);
                    524:                np->use = *p2;
                    525:                free(p2);
                    526:        
                    527:                np->label = SEEKF(wfile, 0L, 2);
                    528:                fappend(wfile, p);
                    529:                WRITEF(wfile,"",1);
                    530:        }
                    531:        pop();
                    532:        *sp++ = newdat(DA, 1, 0);
                    533: }
                    534: 
                    535: ex_nilret()
                    536: {
                    537:        checksp();
                    538:        *sp++ = newdat(DU,0,0); /* put looser onto stack */
                    539:                                /* (should be discarded) */
                    540: }
                    541: 
                    542: reverse(s)
                    543: char *s;
                    544: {
                    545:        register char *p, *q;
                    546:        register char c;
                    547:        int j;
                    548: 
                    549: #define EXCH(a,b)      {c=a;a=b;b=c;}
                    550: 
                    551:        p = q = s;
                    552:        while(*p != EOF)
                    553:                p++;
                    554:        p -= 1+sizeof(char *);
                    555:        while(q < p){
                    556:                for(j=0; j<1+sizeof (char *); j++)
                    557:                        EXCH(p[j], q[j]);
                    558:                q += j;
                    559:                p -= j;
                    560:        }
                    561: }
                    562: 
                    563: /*
                    564:  * produce trace back info
                    565:  */
                    566: char *atfrom[] = {"at\t", "from\t", "", ""};
                    567: tback(flag)
                    568: {
                    569:        register struct si *p;
                    570:        register i;
                    571: 
                    572:        p = gsip;
                    573:        i = 0;
                    574:        if(flag)
                    575:                i = 2;
                    576:        while(p){
                    577:                if(flag==0 && p->suspended)
                    578:                        return;
                    579:                if (p->funlc != 1 || i){        /* skip if at line 0 */
                    580:                        printf("%s%s[%d]%s\n",
                    581:                                atfrom[i],
                    582:                                p->np->namep,
                    583:                                p->funlc - 1,
                    584:                                (p->suspended ? "   *" : "")
                    585:                        );
                    586:                        i |= 1;
                    587:                }
                    588:                p = p->sip;
                    589:        }
                    590: }
                    591: 
                    592: sichk(n)
                    593: struct nlist *n;
                    594: {
                    595:        register struct si *p;
                    596: 
                    597:        p = gsip;
                    598:        while(p){
                    599:                if(n == p->np)
                    600:                        error("si damage -- type ')reset'");
                    601:                p = p->sip;
                    602:        }
                    603: }
                    604: ex_shell(){
                    605: 
                    606:        /* If the environment variable SHELL is defined, attempt to
                    607:         * execute that shell.  If not, or if that exec fails, attempt
                    608:         * to execute the standard shell, /bin/sh
                    609:         */
                    610: 
                    611:        int (*addr)(), (*addr2)();
                    612:        char *getenv();
                    613:        register char *sh;
                    614:        register i;
                    615: 
                    616:        addr = signal(SIGINT, SIG_IGN);
                    617:        addr2 = signal(SIGQUIT, SIG_IGN);
                    618:        i = FORKF(1);
                    619:        if (i == 0){
                    620:                for(i=3; i<20; i++) close(i);
                    621:                signal(SIGINT, SIG_DFL);
                    622:                signal(SIGQUIT, SIG_DFL);
                    623:                if (sh=getenv("SHELL"))
                    624:                        execl(sh, sh, 0);
                    625:                execl("/bin/sh", "sh", 0);
                    626:                printf("no shell!\n");
                    627:                exit(1);
                    628:        }
                    629:        if (i == -1) error("try again");
                    630:        while(wait(0) != i);
                    631:        signal(SIGINT, addr);
                    632:        signal(SIGQUIT, addr2);
                    633: }
                    634: badfnsv(fname)
                    635: char *fname;
                    636: {
                    637: 
                    638:        /* This routine saves the contents of "fname" in the file
                    639:         * named in "bad_fn".  It is called by "funedit" if the
                    640:         * header of a function just read in is messed up (thus,
                    641:         * the entire file is not lost).  Returns 1 if successful,
                    642:         * 0 if not.
                    643:         */
                    644: 
                    645:        register fd1, fd2, len;
                    646:        char buf[512];
                    647: 
                    648:        if ((fd1=OPENF(fname, 0)) < 0 || (fd2=CREATF(bad_fn, 0644)) < 0)
                    649:                return(0);
                    650:        while((len=READF(fd1, buf, 512)) > 0)
                    651:                WRITEF(fd2, buf, len);
                    652:        CLOSEF(fd1);
                    653:        CLOSEF(fd2);
                    654:        return(1);
                    655: }

unix.superglobalmegacorp.com

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