Annotation of 43BSD/ucb/lisp/franz/lam5.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char *rcsid =
                      3:    "$Header: lam5.c,v 1.7 83/12/09 16:36:12 sklower Exp $";
                      4: #endif
                      5: 
                      6: /*                                     -[Fri Aug  5 12:49:06 1983 by jkf]-
                      7:  *     lam5.c                          $Locker:  $
                      8:  * lambda functions
                      9:  *
                     10:  * (c) copyright 1982, Regents of the University of California
                     11:  */
                     12: 
                     13: #include "global.h"
                     14: #include "chkrtab.h"
                     15: #include <ctype.h>
                     16: char *strcpy(), *sprintf();
                     17: 
                     18: /*===========================================
                     19: -
                     20: -      explode functions: aexplode , aexplodec, aexploden
                     21: - The following function partially implement the explode functions for atoms.
                     22: -  The full explode functions are written in lisp and call these for atom args.
                     23: -
                     24: -===========================================*/
                     25: 
                     26: #include "chars.h"
                     27: lispval
                     28: Lexpldx(kind,slashify)
                     29: int kind, slashify;    /* kind = 0 => explode to characters 
                     30:                                = 1 => explode to fixnums (aexploden)
                     31:                           slashify = 0 => do not quote bizarre characters
                     32:                                    = 1 => quote bizarre characters
                     33:                        */
                     34: {
                     35:        int typ, i;
                     36:        char ch, *strb, strbb[BUFSIZ], *alloca();  /* temporary string buffer */
                     37:        register lispval last, handy;
                     38:        extern int uctolc;
                     39:        register char *cp;
                     40:        Savestack(3); /* kludge register save mask */
                     41: #ifdef SPISFP
                     42:        Keepxs();
                     43: #endif
                     44: 
                     45:        chkarg(1,"expldx");
                     46: 
                     47:        handy = Vreadtable->a.clb;
                     48:        chkrtab(handy);
                     49:        handy = lbot->val;
                     50:        *strbuf = 0;
                     51:        typ=TYPE(handy);        /* we only work for a few types */
                     52: 
                     53: 
                     54:        /* put the characters to return in the string buffer strb */
                     55: 
                     56:        switch(typ) {
                     57:        case STRNG:
                     58:                if(slashify && !Xsdc)
                     59:                    errorh1(Vermisc,"Can't explode without string delimiter",nil
                     60:                                          ,FALSE,0,handy);
                     61:                
                     62:                strb = strbb;
                     63:                if(slashify) *strb++ = Xsdc;
                     64:                /* copy string into buffer, escape only occurances of the 
                     65:                   double quoting character if in slashify mode
                     66:                */
                     67:                for(cp = (char *) handy; *cp; cp++)
                     68:                {
                     69:                  if(slashify &&
                     70:                     (*cp == Xsdc || synclass(ctable[*cp])==CESC))
                     71:                         *strb++ = Xesc;
                     72:                  *strb++ = *cp;
                     73:                }
                     74:                if(slashify) *strb++ = Xsdc;
                     75:                *strb = NULL_CHAR ;
                     76:                strb = strbb;
                     77:                break;
                     78: 
                     79:        case ATOM:
                     80:                strb = handy->a.pname;
                     81:                if(slashify && (strb[0]==0)) {
                     82:                        strb = strbb;
                     83:                        strbb[0] = Xdqc;
                     84:                        strbb[1] = Xdqc;
                     85:                        strbb[2] = 0;
                     86:                } else
                     87:        /*common:*/
                     88:                if(slashify != 0)
                     89:                {
                     90:                        char *out = strbb;
                     91:                        unsigned char code;
                     92: 
                     93:                        cp = strb;
                     94:                        strb = strbb;
                     95:                        code = ctable[(*cp)&0177];
                     96:                        switch(synclass(code)) {
                     97:                        case CNUM:
                     98:                                *out++ = Xesc;
                     99:                                break;
                    100:                        case CCHAR:
                    101:                                if(uctolc && isupper((*cp)&0177)) {
                    102:                                    *out++ = Xesc;
                    103:                                }
                    104:                                break;
                    105:                        default:
                    106:                            switch(code&QUTMASK) {
                    107:                            case QWNUNIQ:
                    108:                                    if (cp[1]==0) *out++ = Xesc;
                    109:                                    break;
                    110:                            case QALWAYS:
                    111:                            case QWNFRST:
                    112:                                    *out++ = Xesc;
                    113:                            }
                    114:                        }
                    115:                        *out++ = *cp++;
                    116:                        for(; *cp; cp++)
                    117:                        {
                    118:                                if(((ctable[*cp]&QUTMASK)==QALWAYS) ||
                    119:                                   (uctolc && isupper(*cp)))
                    120:                                        *out++ = Xesc;
                    121:                                *out++ = *cp;
                    122:                        }
                    123:                        *out = 0;
                    124:                }
                    125:                break;
                    126:                                
                    127:        case INT:
                    128:                strb = strbb;
                    129:                sprintf(strb, "%d", lbot->val->i);
                    130:                break;
                    131:        case DOUB:
                    132:                strb = strbb;
                    133:                lfltpr(strb, lbot->val->r);
                    134:                break;
                    135:        case SDOT:
                    136:        {
                    137:                struct _iobuf _strbuf;
                    138:                int count;
                    139:                for((handy = lbot->val), count = 12;
                    140:                    handy->s.CDR!=(lispval) 0;
                    141:                    (handy = handy->s.CDR), count += 12);
                    142:                strb = alloca(count);
                    143: 
                    144:                _strbuf._flag = _IOWRT+_IOSTRG;
                    145:                _strbuf._ptr = strb;
                    146:                _strbuf._cnt = count;
                    147:                pbignum(lbot->val,&_strbuf);
                    148:                putc(0,&_strbuf);
                    149:                break;
                    150:        }
                    151:        default:
                    152:                        errorh1(Vermisc,"EXPLODE ARG MUST BE STRING, SYMBOL, FIXNUM, OR FLONUM",nil,FALSE,0,handy);
                    153:                        Restorestack();
                    154:                        Freexs();
                    155:                        return(nil);
                    156:                }
                    157: 
                    158: 
                    159:        if( strb[0] != NULL_CHAR )      /* if there is something to do */
                    160:        {
                    161:            lispval prev;
                    162: 
                    163:            protect(handy = last = newdot()); 
                    164:            strbuf[1] = NULL_CHAR ;     /* set up for getatom */
                    165:            atmlen = 2;
                    166: 
                    167:            for(i=0; ch = strb[i++]; ) {
                    168:                switch(kind) {
                    169: 
                    170:                  case 0: strbuf[0] = hash = ch;   /* character explode */
                    171:                          last->d.car = (lispval) getatom(TRUE); /* look in oblist */
                    172:                          break;
                    173: 
                    174:                  case 1: 
                    175:                          last->d.car = inewint(ch);
                    176:                          break;
                    177:                }
                    178: 
                    179:                /* advance pointers */
                    180:                prev = last;
                    181:                last->d.cdr = newdot();
                    182:                last = last->d.cdr;
                    183:            }
                    184: 
                    185:            /* end list with a nil pointer */
                    186:            prev->d.cdr = nil;
                    187:            Freexs();
                    188:            Restorestack();
                    189:            return(handy);
                    190:        }
                    191:        Freexs();
                    192:        Restorestack();
                    193:        return(nil);    /* return nil if no characters */
                    194: }
                    195: 
                    196: /*===========================
                    197: -
                    198: - (aexplodec 'atm) returns (a t m)
                    199: - (aexplodec 234) returns (\2 \3 \4)
                    200: -===========================*/
                    201: 
                    202: lispval
                    203: Lxpldc()
                    204: { return(Lexpldx(0,0)); }
                    205: 
                    206: 
                    207: /*===========================
                    208: -
                    209: - (aexploden 'abc) returns (65 66 67)
                    210: - (aexploden 123)  returns (49 50 51)
                    211: -=============================*/
                    212: 
                    213: 
                    214: lispval
                    215: Lxpldn()
                    216: { return(Lexpldx(1,0)); }
                    217: 
                    218: /*===========================
                    219: -
                    220: - (aexplode "123")  returns (\\ \1 \2 \3);
                    221: - (aexplode 123)  returns (\1 \2 \3);
                    222: -=============================*/
                    223: 
                    224: lispval
                    225: Lxplda()
                    226: { return(Lexpldx(0,1)); }
                    227: 
                    228: /*
                    229:  * (argv) returns how many arguments where on the command line which invoked
                    230:  * lisp; (argv i) returns the i'th argument made into an atom;
                    231:  */
                    232: 
                    233: lispval
                    234: Largv()
                    235: {
                    236:        register lispval handy;
                    237:        extern int Xargc;
                    238:        extern char **Xargv;
                    239: 
                    240:        if(lbot-np==0)handy = nil;
                    241:        else handy = lbot->val;
                    242:        
                    243:        if(TYPE(handy)==INT && handy->i>=0 && handy->i<Xargc) {
                    244:                strcpy(strbuf,Xargv[handy->i]);
                    245:                return(getatom(FALSE));
                    246:        } else { 
                    247:                return(inewint(Xargc));
                    248:        }
                    249: }
                    250: /*
                    251:  * (chdir <atom>) executes a chdir command
                    252:  * if successful, return t otherwise returns nil
                    253:  */
                    254: lispval Lchdir(){
                    255:        register char *filenm;
                    256: 
                    257:        chkarg(1,"chdir");
                    258:        filenm = (char *) verify(lbot->val,"chdir - non symbol or string arg");
                    259:        if(chdir(filenm)>=0)
                    260:                return(tatom);
                    261:        else
                    262:                return(nil);
                    263: }
                    264: 
                    265: /* ==========================================================
                    266: -
                    267: -      ascii   - convert from number to ascii character
                    268: -
                    269: - form:(ascii number)
                    270: -
                    271: -      the number is checked so that it is in the range 0-255
                    272: - then it is made a character and returned
                    273: - =========================================================*/
                    274: 
                    275: lispval
                    276: Lascii() 
                    277: {
                    278:        register lispval handy;
                    279: 
                    280:        handy = lbot->val;              /* get argument */
                    281: 
                    282:        if(TYPE(handy) != INT)          /* insure that it is an integer */
                    283:        {       error("argument not an integer",FALSE);
                    284:                return(nil);
                    285:        }
                    286: 
                    287:        if(handy->i < 0 || handy->i > 0377)     /* insure that it is in range*/
                    288:        {       error("argument is out of ascii range",FALSE);
                    289:                return(nil);
                    290:        }
                    291: 
                    292:        strbuf[0] = handy->i ;  /* ok value, make into a char */
                    293:        strbuf[1] = NULL_CHAR;
                    294: 
                    295:        /* lookup and possibly intern the atom given in strbuf */
                    296: 
                    297:        return( (lispval) getatom(TRUE) );
                    298: }
                    299: 
                    300: /*
                    301:  *  boole - maclisp bitwise boolean function
                    302:  *  (boole k x y) where k determines which of 16 possible bitwise 
                    303:  *  truth tables may be applied.  Common values are 1 (and) 6 (xor) 7 (or)
                    304:  *  the result is mapped over each pair of bits on input
                    305:  */
                    306: lispval
                    307: Lboole(){
                    308:        register x, y;
                    309:        register struct argent *mynp;
                    310:        int k;
                    311: 
                    312:        if(np - lbot < 3)
                    313:                error("Boole demands at least 3 args",FALSE);
                    314:        mynp = lbot+AD;
                    315:        k = mynp->val->i & 15;
                    316:        x = (mynp+1)->val->i;
                    317:        for(mynp += 2; mynp < np; mynp++) {
                    318:                y = mynp->val->i;
                    319:                switch(k) {
                    320: 
                    321:                case 0: x = 0;
                    322:                        break;
                    323:                case 1: x = x & y;
                    324:                        break;
                    325:                case 2: x = y & ~x;
                    326:                        break;
                    327:                case 3: x = y;
                    328:                        break;
                    329:                case 4: x = x & ~y;
                    330:                        break;
                    331:                /* case 5:      x = x; break; */
                    332:                case 6: x = x ^ y;
                    333:                        break;
                    334:                case 7: x = x | y;
                    335:                        break;
                    336:                case 8: x = ~(x | y);
                    337:                        break;
                    338:                case 9: x = ~(x ^ y);
                    339:                        break;
                    340:                case 10: x = ~x;
                    341:                        break;
                    342:                case 11: x = ~x | y;
                    343:                        break;
                    344:                case 12: x = ~y;
                    345:                        break;
                    346:                case 13: x = x | ~y;
                    347:                        break;
                    348:                case 14: x = ~x | ~y;
                    349:                        break;
                    350:                case 15: x = -1;
                    351:                }
                    352:        }
                    353:        return(inewint(x));
                    354: }
                    355: lispval
                    356: Lfact()
                    357: {
                    358:        register lispval result, handy;
                    359:        register itemp;
                    360:        Savestack(3); /* fixup entry mask */
                    361: 
                    362:        result = lbot->val;
                    363:        if(TYPE(result)!=INT) error("Factorial of Non-fixnum.  If you want me\
                    364: to calculate fact of > 2^30 We will be here till doomsday!.",FALSE);
                    365:        itemp = result->i;
                    366:        protect(result = newsdot());
                    367:        result->s.CDR=(lispval)0;
                    368:        result->i = 1;
                    369:        for(; itemp > 1; itemp--)
                    370:                dmlad(result,(long)itemp,0L);
                    371:        if(result->s.CDR) 
                    372:        {
                    373:            Restorestack();
                    374:            return(result);
                    375:        }
                    376:        handy = inewint(result->s.I);
                    377:        pruneb(result);
                    378:        Restorestack();
                    379:        return(handy);
                    380: }
                    381: /*
                    382:  * fix -- maclisp floating to fixnum conversion
                    383:  * for the moment, mereley convert floats to ints.
                    384:  * eventual convert to bignum if too big to fit.
                    385:  */
                    386:  lispval Lfix() 
                    387:  {
                    388:        register lispval handy;
                    389:        double floor();
                    390: 
                    391:        chkarg(1,"fix");
                    392:        handy = lbot->val;
                    393:        switch(TYPE(handy)) {
                    394:        default:
                    395:                error("innaproriate arg to fix.",FALSE);
                    396:        case INT:
                    397:        case SDOT:
                    398:                return(handy);
                    399:        case DOUB:
                    400:                return(inewint((int)floor(handy->r)));
                    401:        }
                    402: }
                    403: /*
                    404:  * (frexp <real no>)
                    405:  * returns a dotted pair (<exponent>. <bignum>)
                    406:  * such that bignum is 56 bits long, and if you think of the binary
                    407:  * point occuring after the high order bit, <real no> = 2^<exp> * <bignum>
                    408:  *
                    409:  * myfrexp is an assembly language routine found in bigmath.s to do exactly
                    410:  * what is necessary to accomplish this.
                    411:  * this routine is horribly vax specific.
                    412:  *
                    413:  * Lfix should probably be rewritten to take advantage of myfrexp
                    414:  */
                    415: lispval
                    416: Lfrexp()
                    417: {
                    418:        register lispval handy, result;
                    419:        int exp, hi, lo;
                    420: 
                    421:        Savestack(2);
                    422:        chkarg(1,"frexp");
                    423: 
                    424:        myfrexp(lbot->val->r, &exp, &hi, &lo);
                    425:        if(lo < 0) {
                    426:                /* normalize for bignum */
                    427:                lo &= ~ 0xC0000000;
                    428:                hi += 1;
                    429:        }
                    430:        result = handy = newdot(); 
                    431:        protect(handy);
                    432:        handy->d.car = inewint(exp);
                    433:        if(hi==0&&lo==0) {
                    434:                handy->d.cdr = inewint(0);
                    435:        } else {
                    436:                handy = handy->d.cdr = newsdot();
                    437:                handy->s.I = lo;
                    438:                handy = handy->s.CDR = newdot();
                    439:                handy->s.I = hi;
                    440:                handy->s.CDR = 0;
                    441:        }
                    442:        np--;
                    443:        Restorestack();
                    444:        return(result);
                    445: }
                    446: 
                    447: #define SIGFPE 8
                    448: #define B 1073741824.0
                    449: static double table[] = { 1.0, B, B*B, B*B*B, B*B*B*B, 0.0};
                    450: 
                    451: lispval
                    452: Lfloat()
                    453: {
                    454:        register lispval handy,result;
                    455:        register double sum = 0;
                    456:        register int count;
                    457:        chkarg(1,"float");
                    458:        handy = lbot->val;
                    459:        switch(TYPE(handy))
                    460:        {
                    461:          case DOUB: return(handy);
                    462: 
                    463: 
                    464:          case INT:  result = newdoub();
                    465:                     result->r = (double) handy->i;
                    466:                     return(result);
                    467:          case SDOT: 
                    468:          {
                    469:                for(handy = lbot->val, count = 0;
                    470:                    count < 5;
                    471:                    count++, handy = handy->s.CDR) {
                    472:                        sum += handy->s.I * table[count];
                    473:                        if(handy->s.CDR==(lispval)0) goto done;
                    474:                }
                    475:                kill(getpid(),SIGFPE);
                    476:        done:
                    477:                result = newdoub();
                    478:                result->r = sum;
                    479:                return(result);
                    480:        }
                    481:          default: errorh1(Vermisc,"Bad argument to float",nil,FALSE,0,handy);
                    482:          /* NOTREACHED */
                    483:        }
                    484: }
                    485: double
                    486: Ifloat(handy)
                    487: register lispval handy;
                    488: {
                    489:        register double sum = 0.0; register int count=0;
                    490:        for(; count < 5; count++, handy = handy->s.CDR) {
                    491:                sum += handy->s.I * table[count];
                    492:                if(handy->s.CDR==(lispval)0) goto done;
                    493:        }
                    494:        kill(getpid(),SIGFPE);
                    495:        done:
                    496:        return(sum);
                    497: }
                    498: 
                    499: /* Lbreak ***************************************************************/
                    500: /* If first argument is not nil, this is evaluated and printed.  Then  */
                    501: /* error is called with the "breaking" message.                                */
                    502: lispval Lbreak() {
                    503: 
                    504:        if (np > lbot) {
                    505:                printr(lbot->val,poport);
                    506:                dmpport(poport);
                    507:        }
                    508:        return(error("",TRUE));
                    509: }
                    510: 
                    511: 
                    512: lispval
                    513: LDivide() {
                    514:        register lispval result, work;
                    515:        register struct argent *mynp;
                    516:        lispval quo, rem, arg1, arg2; struct sdot dummy, dum2;
                    517:        Savestack(3);
                    518: 
                    519:        chkarg(2,"Divide");
                    520:        mynp = lbot;
                    521:        work = mynp++->val;
                    522:        switch(TYPE(work)) {
                    523:        case INT:
                    524:                arg1 = (lispval) &dummy;
                    525:                dummy.I = work->i;
                    526:                dummy.CDR = (lispval) 0;
                    527:                break;
                    528:        case SDOT:
                    529:                arg1 = work;
                    530:                break;
                    531:        urk:
                    532:        default:
                    533:                error("First arg to divide neither a bignum nor int.",FALSE);
                    534:        }
                    535:        work = mynp->val;
                    536:        switch(TYPE(work)) {
                    537:        case INT:
                    538:                arg2 = (lispval) &dum2;
                    539:                dum2.I = work->i;
                    540:                dum2.CDR = (lispval) 0;
                    541:                break;
                    542:        case SDOT:
                    543:                arg2 = work;
                    544:                break;
                    545:        default:
                    546:                goto urk;
                    547:        }
                    548:        divbig(arg1,arg2, &quo, &rem);
                    549:        protect(quo);
                    550:        if(rem==((lispval)&dummy))
                    551:                rem = inewint(dummy.I);
                    552:        protect(rem);
                    553:        protect(result = work = newdot());
                    554:        work->d.car = quo;
                    555:        (work->d.cdr = newdot())->d.car = rem;
                    556:        Restorestack();
                    557:        return(result);
                    558: }
                    559: 
                    560: lispval LEmuldiv(){
                    561:        register struct argent * mynp = lbot+AD;
                    562:        register lispval work, result;
                    563:        int quo, rem;
                    564:        Savestack(3); /* fix register mask */
                    565: 
                    566:        /* (Emuldiv mul1 mult2 add quo) => 
                    567:                temp = mul1 + mul2 + sext(add);
                    568:                result = (list temp/quo temp%quo);
                    569:                to mix C and lisp a bit */
                    570: 
                    571:        Imuldiv(mynp[0].val->i, mynp[1].val->i, mynp[2].val->i,
                    572:                mynp[3].val->i, &quo, &rem);
                    573:        protect(result=newdot());
                    574:        (result->d.car=inewint(quo));
                    575:        work = result->d.cdr = newdot();
                    576:        (work->d.car=inewint(rem));
                    577:        Restorestack();
                    578:        return(result);
                    579: }

unix.superglobalmegacorp.com

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