Annotation of 40BSD/cmd/lisp/lam5.c, revision 1.1

1.1     ! root        1: static char *sccsid = "@(#)lam5.c      34.1 10/3/80";
        !             2: 
        !             3: #include "global.h"
        !             4: #include "chkrtab.h"
        !             5: 
        !             6: /*===========================================
        !             7: -
        !             8: -      explode functions: aexplode , aexplodec, aexploden
        !             9: - The following function partially implement the explode functions for atoms.
        !            10: -  The full explode functions are written in lisp and call these for atom args.
        !            11: -
        !            12: -===========================================*/
        !            13: 
        !            14: #include "chars.h"
        !            15: lispval
        !            16: Lexpldx(kind,slashify)
        !            17: int kind, slashify;    /* kind = 0 => explode to characters 
        !            18:                                = 1 => explode to fixnums (aexploden)
        !            19:                           slashify = 0 => do not quote bizarre characters
        !            20:                                    = 1 => quote bizarre characters
        !            21:                        */
        !            22: {
        !            23:        int typ, i;
        !            24:        char ch, *strb, strbb[BUFSIZ];  /* temporary string buffer */
        !            25:        register lispval last, handy;
        !            26:        register char *cp;
        !            27:        char Idqc = Xdqc;
        !            28:        snpand(4); /* kludge register save mask */
        !            29: 
        !            30:        chkarg(1,"expldx");
        !            31: 
        !            32:        handy = Vreadtable->a.clb;
        !            33:        chkrtab(handy);
        !            34:        handy = lbot->val;
        !            35:        *strbuf = 0;
        !            36:        typ=TYPE(handy);        /* we only work for a few types */
        !            37: 
        !            38: 
        !            39:        /* put the characters to return in the string buffer strb */
        !            40: 
        !            41:        switch(typ) {
        !            42:        case STRNG:
        !            43:                if(slashify && !Xsdc)
        !            44:                    errorh(Vermisc,"Can't explode without string delimiter",nil
        !            45:                                          ,FALSE,0,handy);
        !            46:                
        !            47:                strb = strbb;
        !            48:                if(slashify) *strb++ = Xsdc;
        !            49:                /* copy string into buffer, escape only occurances of the 
        !            50:                   double quoting character if in slashify mode
        !            51:                */
        !            52:                for(cp = (char *) handy; *cp; cp++)
        !            53:                {
        !            54:                  if(slashify &&
        !            55:                     (*cp == Xsdc || ctable[*cp]==VESC))
        !            56:                         *strb++ = Xesc;
        !            57:                  *strb++ = *cp;
        !            58:                }
        !            59:                if(slashify) *strb++ = Xsdc;
        !            60:                *strb = NULL_CHAR ;
        !            61:                strb = strbb;
        !            62:                break;
        !            63: 
        !            64:        case ATOM:
        !            65:                strb = handy->a.pname;
        !            66:                if(strb[0]==0) {
        !            67:                        strb = strbb;
        !            68:                        strbb[0] = Xdqc;
        !            69:                        strbb[1] = Xdqc;
        !            70:                        strbb[2] = 0;
        !            71:                } else
        !            72:        common:
        !            73:                if(slashify != 0)
        !            74:                {
        !            75:                        register char *out = strbb;
        !            76:                        cp = strb;
        !            77:                        strb = strbb;
        !            78:                        if(ctable[(*cp)&0177]==VNUM)
        !            79:                                *out++ = Xesc;
        !            80:                        for(; *cp; cp++)
        !            81:                        {
        !            82:                                if(ctable[*cp]& QUTMASK)
        !            83:                                        *out++ = Xesc;
        !            84:                                *out++ = *cp;
        !            85:                        }
        !            86:                        *out = 0;
        !            87:                }
        !            88:                                
        !            89:                break;
        !            90:        case INT:
        !            91:                strb = strbb;
        !            92:                sprintf(strb, "%d", lbot->val->i);
        !            93:                break;
        !            94:        case DOUB:
        !            95:                strb = strbb;
        !            96:                lfltpr(strb, lbot->val->r);
        !            97:                break;
        !            98:        case SDOT:
        !            99:        {
        !           100:                struct _iobuf _strbuf;
        !           101:                register count;
        !           102:                for((handy = lbot->val), count = 12;
        !           103:                    handy->s.CDR!=(lispval) 0;
        !           104:                    (handy = handy->s.CDR), count += 12);
        !           105:                strb = (char *) alloca(count);
        !           106: 
        !           107:                _strbuf._flag = _IOWRT+_IOSTRG;
        !           108:                _strbuf._ptr = strb;
        !           109:                _strbuf._cnt = count;
        !           110:                pbignum(lbot->val,&_strbuf);
        !           111:                putc(0,&_strbuf);
        !           112:                break;
        !           113:        }
        !           114:        default:
        !           115:                        errorh(Vermisc,"EXPLODE ARG MUST BE STRING, SYMBOL, FIXNUM, OR FLONUM",nil,FALSE,0,handy);
        !           116:                        return(nil);
        !           117:                }
        !           118: 
        !           119: 
        !           120:        if( strb[0] != NULL_CHAR )      /* if there is something to do */
        !           121:        {
        !           122:            register lispval prev;
        !           123: 
        !           124:            protect(handy = last = newdot()); 
        !           125:            strbuf[1] = NULL_CHAR ;     /* set up for getatom */
        !           126:            atmlen = 2;
        !           127: 
        !           128:            for(i=0; ch = strb[i++]; ) {
        !           129:                switch(kind) {
        !           130: 
        !           131:                  case 0: strbuf[0] = hash = ch;   /* character explode */
        !           132:                          last->d.car = (lispval) getatom(); /* look in oblist */
        !           133:                          break;
        !           134: 
        !           135:                  case 1: 
        !           136:                          last->d.car = inewint(ch);
        !           137:                          break;
        !           138:                }
        !           139: 
        !           140:                /* advance pointers */
        !           141:                prev = last;
        !           142:                last->d.cdr = newdot();
        !           143:                last = last->d.cdr;
        !           144:            }
        !           145: 
        !           146:            /* end list with a nil pointer */
        !           147:            prev->d.cdr = nil;
        !           148:            return(handy);
        !           149:        }
        !           150:        else return(nil);       /* return nil if no characters */
        !           151: }
        !           152: 
        !           153: /*===========================
        !           154: -
        !           155: - (aexplodec 'atm) returns (a t m)
        !           156: - (aexplodec 234) returns (\2 \3 \4)
        !           157: -===========================*/
        !           158: 
        !           159: lispval
        !           160: Lexpldc()
        !           161: { return(Lexpldx(0,0)); }
        !           162: 
        !           163: 
        !           164: /*===========================
        !           165: -
        !           166: - (aexploden 'abc) returns (65 66 67)
        !           167: - (aexploden 123)  returns (49 50 51)
        !           168: -=============================*/
        !           169: 
        !           170: 
        !           171: lispval
        !           172: Lexpldn()
        !           173: { return(Lexpldx(1,0)); }
        !           174: 
        !           175: /*===========================
        !           176: -
        !           177: - (aexplode "123")  returns (\\ \1 \2 \3);
        !           178: - (aexplode 123)  returns (\1 \2 \3);
        !           179: -=============================*/
        !           180: 
        !           181: lispval
        !           182: Lexplda()
        !           183: { return(Lexpldx(0,1)); }
        !           184: 
        !           185: /*
        !           186:  * (argv) returns how many arguments where on the command line which invoked
        !           187:  * lisp; (argv i) returns the i'th argument made into an atom;
        !           188:  */
        !           189: 
        !           190: lispval
        !           191: Largv()
        !           192: {
        !           193:        register lispval handy;
        !           194:        register index;
        !           195:        register char *base;
        !           196:        char c;
        !           197:        extern int Xargc;
        !           198:        extern char **Xargv;
        !           199:        snpand(3);
        !           200: 
        !           201:        if(lbot-np==0)protect(nil);
        !           202:        handy = lbot->val;
        !           203:        
        !           204:        if(TYPE(handy)==INT && handy->i>=0 && handy->i<Xargc) {
        !           205:                strcpy(strbuf,Xargv[handy->i]);
        !           206:                return(getatom());
        !           207:        } else { 
        !           208:                return(inewint(Xargc));
        !           209:        }
        !           210: }
        !           211: /*
        !           212:  * (chdir <atom>) executes a chdir command
        !           213:  * if successful, return t otherwise returns nil
        !           214:  */
        !           215: lispval Lchdir(){
        !           216:        register char *filenm;
        !           217: 
        !           218:        chkarg(1,"chdir");
        !           219:        filenm = (char *) verify(lbot->val,"chdir - non symbol or string arg");
        !           220:        if(chdir(filenm)>=0)
        !           221:                return(tatom);
        !           222:        else
        !           223:                return(nil);
        !           224: }
        !           225: 
        !           226: /* ==========================================================
        !           227: -
        !           228: -      ascii   - convert from number to ascii character
        !           229: -
        !           230: - form:(ascii number)
        !           231: -
        !           232: -      the number is checked so that it is in the range 0-255
        !           233: - then it is made a character and returned
        !           234: - =========================================================*/
        !           235: 
        !           236: lispval
        !           237: Lascii() 
        !           238: {
        !           239:        register lispval handy;
        !           240: 
        !           241:        handy = lbot->val;              /* get argument */
        !           242: 
        !           243:        if(TYPE(handy) != INT)          /* insure that it is an integer */
        !           244:        {       error("argument not an integer",FALSE);
        !           245:                return(nil);
        !           246:        }
        !           247: 
        !           248:        if(handy->i < 0 || handy->i > 0377)     /* insure that it is in range*/
        !           249:        {       error("argument is out of ascii range",FALSE);
        !           250:                return(nil);
        !           251:        }
        !           252: 
        !           253:        strbuf[0] = handy->i ;  /* ok value, make into a char */
        !           254:        strbuf[1] = NULL_CHAR;
        !           255: 
        !           256:        /* lookup and possibly intern the atom given in strbuf */
        !           257: 
        !           258:        return( (lispval) getatom() );
        !           259: }
        !           260: 
        !           261: /*
        !           262:  *  boole - maclisp bitwise boolean function
        !           263:  *  (boole k x y) where k determines which of 16 possible bitwise 
        !           264:  *  truth tables may be applied.  Common values are 1 (and) 6 (xor) 7 (or)
        !           265:  *  the result is mapped over each pair of bits on input
        !           266:  */
        !           267: lispval
        !           268: Lboole(){
        !           269:        register x, y;
        !           270:        register lispval result;
        !           271:        register struct argent *mynp;
        !           272:        int k;
        !           273: 
        !           274:        if(np - lbot < 3)
        !           275:                error("Boole demands at least 3 args",FALSE);
        !           276:        mynp = lbot+AD;
        !           277:        k = mynp->val->i & 15;
        !           278:        x = (mynp+1)->val->i;
        !           279:        for(mynp += 2; mynp < np; mynp++) {
        !           280:                y = mynp->val->i;
        !           281:                switch(k) {
        !           282: 
        !           283:                case 0: x = 0;
        !           284:                        break;
        !           285:                case 1: x = x & y;
        !           286:                        break;
        !           287:                case 2: x = y & ~x;
        !           288:                        break;
        !           289:                case 3: x = y;
        !           290:                        break;
        !           291:                case 4: x = x & ~y;
        !           292:                        break;
        !           293:                /* case 5:      x = x; break; */
        !           294:                case 6: x = x ^ y;
        !           295:                        break;
        !           296:                case 7: x = x | y;
        !           297:                        break;
        !           298:                case 8: x = ~(x | y);
        !           299:                        break;
        !           300:                case 9: x = ~(x ^ y);
        !           301:                        break;
        !           302:                case 10: x = ~x;
        !           303:                        break;
        !           304:                case 11: x = ~x | y;
        !           305:                        break;
        !           306:                case 12: x = ~y;
        !           307:                        break;
        !           308:                case 13: x = x | ~y;
        !           309:                        break;
        !           310:                case 14: x = ~x | ~y;
        !           311:                        break;
        !           312:                case 15: x = -1;
        !           313:                }
        !           314:        }
        !           315:        return(inewint(x));
        !           316: }
        !           317: lispval
        !           318: Lfact()
        !           319: {
        !           320:        register lispval result, handy;
        !           321:        register itemp;
        !           322:        snpand(3); /* fixup entry mask */
        !           323: 
        !           324:        result = lbot->val;
        !           325:        if(TYPE(result)!=INT) error("Factorial of Non-fixnum.  If you want me\
        !           326: to calculate fact of > 2^30 We will be here till doomsday!.",FALSE);
        !           327:        itemp = result->i;
        !           328:        protect(result = newsdot());
        !           329:        result->s.CDR=(lispval)0;
        !           330:        result->i = 1;
        !           331:        for(; itemp > 1; itemp--)
        !           332:                dmlad(result,itemp,0);
        !           333:        if(result->s.CDR) return(result);
        !           334:        (handy = newint())->i = result->i;
        !           335:        return(handy);
        !           336: }
        !           337: /*
        !           338:  * fix -- maclisp floating to fixnum conversion
        !           339:  * for the moment, mereley convert floats to ints.
        !           340:  * eventual convert to bignum if too big to fit.
        !           341:  */
        !           342:  lispval Lfix() 
        !           343:  {
        !           344:        register lispval result, handy;
        !           345: 
        !           346:        chkarg(1,"fix");
        !           347:        handy = lbot->val;
        !           348:        switch(TYPE(handy)) {
        !           349:        default:
        !           350:                error("innaproriate arg to fix.",FALSE);
        !           351:        case INT:
        !           352:        case SDOT:
        !           353:                return(handy);
        !           354:        case DOUB:
        !           355:                if(handy->r >= 0)
        !           356:                        return(inewint((int)handy->r));
        !           357:                else
        !           358:                        return(inewint(((int)handy->r)-1));
        !           359:        }
        !           360: }
        !           361: #define SIGFPE 8
        !           362: #define B 1073741824.0
        !           363: static double table[] = { 1.0, B, B*B, B*B*B, B*B*B*B, 0.0};
        !           364: 
        !           365: lispval
        !           366: Lfloat()
        !           367: {
        !           368:        register lispval handy,result;
        !           369:        register double sum = 0;
        !           370:        register int count;
        !           371:        chkarg(1,"float");
        !           372:        handy = lbot->val;
        !           373:        switch(TYPE(handy))
        !           374:        {
        !           375:          case DOUB: return(handy);
        !           376: 
        !           377: 
        !           378:          case INT:  result = newdoub();
        !           379:                     result->r = (double) handy->i;
        !           380:                     return(result);
        !           381:          case SDOT: 
        !           382:          {
        !           383:                for(handy = lbot->val, count = 0;
        !           384:                    count < 5;
        !           385:                    count++, handy = handy->s.CDR) {
        !           386:                        sum += handy->s.I * table[count];
        !           387:                        if(handy->s.CDR==(lispval)0) goto done;
        !           388:                }
        !           389:                kill(getpid(),SIGFPE);
        !           390:        done:
        !           391:                result = newdoub();
        !           392:                result->r = sum;
        !           393:                return(result);
        !           394:        }
        !           395:          default: errorh(Vermisc,"Bad argument to float",nil,FALSE,0,handy);
        !           396:        }
        !           397: }
        !           398: 
        !           399: 
        !           400: /* Lbreak ***************************************************************/
        !           401: /* If first argument is not nil, this is evaluated and printed.  Then  */
        !           402: /* error is called with the "breaking" message.                                */
        !           403: lispval Lbreak() {
        !           404:        register lispval hold;
        !           405: 
        !           406:        if (np > lbot) {
        !           407:                printr(lbot->val,poport);
        !           408:                dmpport(poport);
        !           409:        }
        !           410:        return(error("",TRUE));
        !           411: }
        !           412: 
        !           413: 
        !           414: lispval LDivide() {
        !           415:        register lispval result, work, temp;
        !           416:        register struct argent *mynp;
        !           417:        register struct argent *lbot, *np;
        !           418:        int typ;
        !           419:        lispval quo, rem; struct sdot dummy;
        !           420: 
        !           421:        chkarg(2,"Divide");
        !           422:        mynp = lbot;
        !           423:        result = mynp->val;
        !           424:        work = (mynp+1)->val;
        !           425: 
        !           426:        if((typ=TYPE(result))==INT) {
        !           427:                protect(temp=newsdot());
        !           428:                temp->i = result->i;
        !           429:                result = temp;
        !           430:        } else if (typ!=SDOT)
        !           431:                error("First arg to divide neither a bignum nor int.",FALSE);
        !           432:        typ = TYPE(work);
        !           433:        if(typ != INT && typ != SDOT)
        !           434:                error("second arg to Divide neither an sdot nor an int.",FALSE);
        !           435:        if(typ == INT) {
        !           436:                dummy.CDR = (lispval) 0;
        !           437:                dummy.I = work->i;
        !           438:                work = (lispval) &dummy;
        !           439:        }
        !           440:        divbig(result,work, &quo, &rem);
        !           441:        protect(quo);
        !           442:        if(rem==((lispval) &dummy))
        !           443:                protect(rem = inewint(dummy.I));
        !           444:        protect(result = work = newdot());
        !           445:        work->d.car = quo;
        !           446:        (work->d.cdr = newdot())->d.car = rem;
        !           447:        return(result);
        !           448: }
        !           449: 
        !           450: lispval LEmuldiv(){
        !           451:        register struct argent * mynp = lbot+AD;
        !           452:        register lispval work, result;
        !           453:        int quo, rem;
        !           454:        snpand(3); /* fix register mask */
        !           455: 
        !           456:        /* (Emuldiv mul1 mult2 add quo) => 
        !           457:                temp = mul1 + mul2 + sext(add);
        !           458:                result = (list temp/quo temp%quo);
        !           459:                to mix C and lisp a bit */
        !           460: 
        !           461:        Imuldiv(mynp[0].val->i, mynp[1].val->i, mynp[2].val->i,
        !           462:                mynp[3].val->i, &quo, &rem);
        !           463:        protect(result=newdot());
        !           464:        (result->d.car=inewint(quo));
        !           465:        work = result->d.cdr = newdot();
        !           466:        (work->d.car=inewint(rem));
        !           467:        return(result);
        !           468: }
        !           469: static Imuldiv() {
        !           470: asm("  emul    4(ap),8(ap),12(ap),r0");
        !           471: asm("  ediv    16(ap),r0,*20(ap),*24(ap)");
        !           472: }
        !           473: 
        !           474: 

unix.superglobalmegacorp.com

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