Annotation of coherent/a/usr/bob/korn/var.c, revision 1.1

1.1     ! root        1: static char *RCSid = "$Header: var.c,v 3.1 88/11/03 09:18:22 egisin Exp $";
        !             2: 
        !             3: #include <stddef.h>
        !             4: #include <stdlib.h>
        !             5: #include <string.h>
        !             6: #include <errno.h>
        !             7: #include <setjmp.h>
        !             8: #include <time.h>
        !             9: #include <sys/types.h>
        !            10: #include "sh.h"
        !            11: #include "table.h"
        !            12: #include "expand.h"
        !            13: 
        !            14: /*
        !            15:  * Variables
        !            16:  *
        !            17:  * WARNING: unreadable code, needs a rewrite
        !            18:  *
        !            19:  * if (flag&INTEGER), val.i contains integer value, and type contains base.
        !            20:  * otherwise, (val.s + type) contains string value.
        !            21:  * if (flag&EXPORT), val.s contains "name=value" for E-Z exporting.
        !            22:  */
        !            23: char   null [] = "";
        !            24: static struct tbl vtemp;
        !            25: static void getspec(), setspec();
        !            26: static void export ARGS((struct tbl *, char *val));
        !            27: static int special ARGS ((char *name));
        !            28: 
        !            29: /*
        !            30:  * create a new block for function calls and simple commands
        !            31:  * assume caller has allocated and set up e.loc
        !            32:  */
        !            33: void
        !            34: newblock()
        !            35: {
        !            36:        register struct block *l = e.loc;
        !            37:        static char *empty[] = {""};
        !            38: 
        !            39:        ainit(&l->area);
        !            40:        l->argc = 0;
        !            41:        l->argv = empty;
        !            42:        l->exit = l->error = NULL;
        !            43:        tinit(&l->vars, &l->area);
        !            44:        tinit(&l->funs, &l->area);
        !            45: }
        !            46: 
        !            47: /*
        !            48:  * pop a block handling special variables
        !            49:  */
        !            50: void
        !            51: popblock()
        !            52: {
        !            53:        register struct block *l = e.loc;
        !            54:        register struct tbl *vp, **vpp = l->vars.tbls;
        !            55:        register int i;
        !            56: 
        !            57:        e.loc = l->next;        /* pop block */
        !            58:        for (i = l->vars.size; --i >= 0; )
        !            59:                if ((vp = *vpp++) != NULL && (vp->flag&SPECIAL))
        !            60:                        setspec(global(vp->name));
        !            61:        afreeall(&l->area);
        !            62: }
        !            63: 
        !            64: /*
        !            65:  * Search for variable, if not found create globally.
        !            66:  */
        !            67: struct tbl *
        !            68: global(n)
        !            69:        register char *n;
        !            70: {
        !            71:        register struct block *l = e.loc;
        !            72:        register struct tbl *vp;
        !            73:        register int c;
        !            74:        unsigned h = hash(n);
        !            75: 
        !            76:        c = n[0];
        !            77:        if (digit(c)) {
        !            78:                vp = &vtemp;
        !            79:                lastarea = ATEMP;
        !            80:                vp->flag = (DEFINED|RDONLY);
        !            81:                vp->type = 0;
        !            82:                *vp->name = c;  /* should strncpy */
        !            83:                for (c = 0; digit(*n) && c < 1000; n++)
        !            84:                        c = c*10 + *n-'0';
        !            85:                if (c <= l->argc)
        !            86:                        setstr(vp, l->argv[c]);
        !            87:                return vp;
        !            88:        } else
        !            89:        if (!letter(c)) {
        !            90:                vp = &vtemp;
        !            91:                lastarea = ATEMP;
        !            92:                vp->flag = (DEFINED|RDONLY);
        !            93:                vp->type = 0;
        !            94:                *vp->name = c;
        !            95:                if (n[1] != '\0')
        !            96:                        return vp;
        !            97:                vp->flag |= ISSET|INTEGER;
        !            98:                switch (c) {
        !            99:                  case '$':
        !           100:                        vp->val.i = getpid();
        !           101:                        break;
        !           102:                  case '!':
        !           103:                        vp->val.i = async;
        !           104:                        break;
        !           105:                  case '?':
        !           106:                        vp->val.i = exstat;
        !           107:                        break;
        !           108:                  case '#':
        !           109:                        vp->val.i = l->argc;
        !           110:                        break;
        !           111:                  case '-':
        !           112:                        vp->flag &= ~ INTEGER;
        !           113:                        vp->val.s = getoptions();
        !           114:                        break;
        !           115:                  default:
        !           116:                        vp->flag &= ~(ISSET|INTEGER);
        !           117:                }
        !           118:                return vp;
        !           119:        }
        !           120:        for (l = e.loc; l != NULL; l = l->next) {
        !           121:                vp = tsearch(&l->vars, n, h);
        !           122:                lastarea = &l->area;
        !           123:                if (vp != NULL)
        !           124:                        return vp;
        !           125:                if (l->next == NULL)
        !           126:                        break;
        !           127:        }
        !           128:        vp = tenter(&l->vars, n, h);
        !           129:        vp->flag |= DEFINED;
        !           130:        if (special(n))
        !           131:                vp->flag |= SPECIAL;
        !           132:        return vp;
        !           133: }
        !           134: 
        !           135: /*
        !           136:  * Search for local variable, if not found create locally.
        !           137:  */
        !           138: struct tbl *
        !           139: local(n)
        !           140:        register char *n;
        !           141: {
        !           142:        register struct block *l = e.loc;
        !           143:        register struct tbl *vp;
        !           144:        unsigned h = hash(n);
        !           145: 
        !           146:        if (!letter(*n)) {
        !           147:                vp = &vtemp;
        !           148:                lastarea = ATEMP;
        !           149:                vp->flag = (DEFINED|RDONLY);
        !           150:                vp->type = 0;
        !           151:                return vp;
        !           152:        }
        !           153:        vp = tenter(&l->vars, n, h);
        !           154:        lastarea = &l->area;
        !           155:        vp->flag |= DEFINED;
        !           156:        if (special(n))
        !           157:                vp->flag |= SPECIAL;
        !           158:        return vp;
        !           159: }
        !           160: 
        !           161: /* get variable string value */
        !           162: char *
        !           163: strval(vp)
        !           164:        register struct tbl *vp;
        !           165: {
        !           166:        register char *s;
        !           167:        static char strbuf[40];
        !           168: 
        !           169:        if ((vp->flag&SPECIAL))
        !           170:                getspec(vp);
        !           171:        if (!(vp->flag&ISSET))
        !           172:                return null;    /* special to dollar() */
        !           173:        if (!(vp->flag&INTEGER))        /* string source */
        !           174:                s = vp->val.s + vp->type;
        !           175:        else {                          /* integer source */
        !           176:                register unsigned long n;
        !           177:                register int base;
        !           178: 
        !           179:                s = strbuf + sizeof(strbuf);
        !           180:                n = (vp->val.i < 0) ? -vp->val.i : vp->val.i;
        !           181:                base = (vp->type == 0) ? 10 : vp->type;
        !           182: 
        !           183:                *--s = '\0';
        !           184:                do {
        !           185:                        *--s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[n%base];
        !           186:                        n /= base;
        !           187:                } while (n != 0);
        !           188:                /* todo: should we output base# ? */
        !           189:                if (vp->val.i < 0)
        !           190:                        *--s = '-';
        !           191:        }
        !           192:        return s;
        !           193: }
        !           194: 
        !           195: /* get variable integer value */
        !           196: long
        !           197: intval(vp)
        !           198:        register struct tbl *vp;
        !           199: {
        !           200:        register struct tbl *vq;
        !           201: 
        !           202:        if ((vp->flag&SPECIAL))
        !           203:                getspec(vp);
        !           204:        if ((vp->flag&INTEGER))
        !           205:                return vp->val.i;
        !           206:        vq = &vtemp;
        !           207:        vq->flag = (INTEGER);
        !           208:        vq->type = 0;
        !           209:        strint(vq, vp);
        !           210:        return vq->val.i;
        !           211: }
        !           212: 
        !           213: /* set variable to string value */
        !           214: void
        !           215: setstr(vq, s)
        !           216:        register struct tbl *vq;
        !           217:        char *s;
        !           218: {
        !           219:        if (!(vq->flag&INTEGER)) { /* string dest */
        !           220:                if ((vq->flag&ALLOC))
        !           221:                        afree((Void*)vq->val.s, lastarea);
        !           222:                vq->flag &= ~ (ISSET|ALLOC);
        !           223:                vq->type = 0;
        !           224:                if ((vq->flag&EXPORT))
        !           225:                        export(vq, s);
        !           226:                else
        !           227:                        vq->val.s = strsave(s, lastarea);
        !           228:                vq->flag |= ALLOC;
        !           229:        } else {                /* integer dest */
        !           230:                register struct tbl *vp = &vtemp;       
        !           231:                vp->flag = (DEFINED|ISSET);
        !           232:                vp->type = 0;
        !           233:                vp->val.s = s;
        !           234:                strint(vq, vp);
        !           235:        }
        !           236:        vq->flag |= ISSET;
        !           237:        if ((vq->flag&SPECIAL))
        !           238:                setspec(vq);
        !           239: }
        !           240:        
        !           241: /* convert variable to integer variable */
        !           242: struct tbl *
        !           243: strint(vq, vp)
        !           244:        register struct tbl *vq, *vp;
        !           245: {
        !           246:        register char *s = vp->val.s + vp->type;
        !           247:        register int c;
        !           248:        int base, neg = 0;
        !           249:        
        !           250:        vq->flag |= INTEGER;
        !           251:        if ((vp->flag&INTEGER)) {
        !           252:                vq->val.i = vp->val.i;
        !           253:                return vq;
        !           254:        }
        !           255:        vq->val.i = 0;
        !           256:        base = 10;
        !           257:        for (c = *s++; c ; c = *s++)
        !           258:                if (c == '-') {
        !           259:                        neg++;
        !           260:                } else if (c == '#') {
        !           261:                        base = vq->type = vq->val.i;
        !           262:                        vq->val.i = 0;
        !           263:                } else if (letnum(c)) {
        !           264:                        if ('0' <= c && c <= '9')
        !           265:                                c -= '0';
        !           266:                        else if ('a' <= c && c <= 'z') /* fuck EBCDIC */
        !           267:                                c -= 'a'-10;
        !           268:                        else if ('A' <= c && c <= 'Z')
        !           269:                                c -= 'A'-10;
        !           270:                        vq->val.i = (vq->val.i*base) + c;
        !           271:                } else
        !           272:                        break;
        !           273:        if (neg)
        !           274:                vq->val.i = -vq->val.i;
        !           275:        if (vq->type < 2 || vq->type > 36)
        !           276:                vq->type = 0;   /* default base (10) */
        !           277:        return vq;
        !           278: }
        !           279: 
        !           280: /* set variable to integer */
        !           281: void
        !           282: setint(vq, n)
        !           283:        register struct tbl *vq;
        !           284:        long n;
        !           285: {
        !           286:        if (!(vq->flag&INTEGER)) {
        !           287:                register struct tbl *vp = &vtemp;
        !           288:                vp->flag = (ISSET|INTEGER);
        !           289:                vp->type = 0;
        !           290:                vp->val.i = n;
        !           291:                setstr(vq, strval(vp)); /* ? */
        !           292:        } else
        !           293:                vq->val.i = n;
        !           294:        vq->flag |= ISSET;
        !           295:        if ((vq->flag&SPECIAL))
        !           296:                setspec(vq);
        !           297: }
        !           298: 
        !           299: /* set variable from enviroment */
        !           300: import(thing)
        !           301:        char *thing;
        !           302: {
        !           303:        register struct tbl *vp;
        !           304:        register char *val;
        !           305: 
        !           306:        val = strchr(thing, '=');
        !           307:        if (val == NULL)
        !           308:                return 0;
        !           309:        *val = '\0';
        !           310:        vp = local(thing);
        !           311:        *val++ = '=';
        !           312:        vp->flag |= DEFINED|ISSET|EXPORT;
        !           313:        vp->val.s = thing;
        !           314:        vp->type = val - thing;
        !           315:        if ((vp->flag&SPECIAL))
        !           316:                setspec(vp);
        !           317:        return 1;
        !           318: }
        !           319: 
        !           320: /*
        !           321:  * make vp->val.s be "name=value" for quick exporting.
        !           322:  */
        !           323: static void
        !           324: export(vp, val)
        !           325:        register struct tbl *vp;
        !           326:        char *val;
        !           327: {
        !           328:        register char *cp, *xp;
        !           329:        char *op = (vp->flag&ALLOC) ? vp->val.s : NULL;
        !           330: 
        !           331:        xp = (char*)alloc(strlen(vp->name) + strlen(val) + 2, lastarea);
        !           332:        vp->flag |= ALLOC;
        !           333:        vp->val.s = xp;
        !           334:        for (cp = vp->name; (*xp = *cp++) != '\0'; xp++)
        !           335:                ;
        !           336:        *xp++ = '=';
        !           337:        vp->type = xp - vp->val.s; /* offset to value */
        !           338:        for (cp = val; (*xp++ = *cp++) != '\0'; )
        !           339:                ;
        !           340:        if (op != NULL)
        !           341:                afree((Void*)op, lastarea);
        !           342: }
        !           343: 
        !           344: /*
        !           345:  * lookup variable (according to (set&LOCAL)),
        !           346:  * set its attributes (INTEGER, RDONLY, EXPORT, TRACE),
        !           347:  * and optionally set its value if an assignment.
        !           348:  */
        !           349: struct tbl *
        !           350: typeset(var, set, clr)
        !           351:        register char *var;
        !           352:        int clr, set;
        !           353: {
        !           354:        register struct tbl *vp;
        !           355:        register char *val;
        !           356: 
        !           357:        /* check for valid variable name, search for value */
        !           358:        val = var;
        !           359:        if (!letter(*val))
        !           360:                return NULL;
        !           361:        for (val++; *val != '\0'; val++)
        !           362:                if (*val == '=')
        !           363:                        break;
        !           364:                else if (letnum(*val))
        !           365:                        ;
        !           366:                else
        !           367:                        return NULL;
        !           368:        if (*val == '=')
        !           369:                *val = '\0';
        !           370:        else
        !           371:                val = NULL;
        !           372:        vp = (set&LOCAL) ? local(var) : global(var);
        !           373:        set &= ~ LOCAL;
        !           374:        if (val != NULL)
        !           375:                *val++ = '=';
        !           376: 
        !           377:        if (!(vp->flag&ISSET))
        !           378:                vp->flag = vp->flag & ~clr | set;
        !           379:        else
        !           380:            if (!(vp->flag&INTEGER) && (set&INTEGER)) {
        !           381:                /* string to integer */
        !           382:                vtemp.flag = (ISSET);
        !           383:                vtemp.type = 0;
        !           384:                vtemp.val.s = vp->val.s + vp->type;
        !           385:                if ((vp->flag&ALLOC))
        !           386:                        afree((Void*)vp->val.s, lastarea); /* dangerous, used later */
        !           387:                vp->flag &= ~ ALLOC;
        !           388:                vp->flag |= INTEGER;
        !           389:                vp->type = 0;
        !           390:                strint(vp, &vtemp);
        !           391:            } else
        !           392:            if ((clr&INTEGER) && (vp->flag&INTEGER)) {
        !           393:                /* integer to string */
        !           394:                vtemp.val.s = strval(vp);
        !           395:                vp->flag &= ~ INTEGER;
        !           396:                setstr(vp, vtemp.val.s);
        !           397:            }
        !           398: 
        !           399:        vp->flag = vp->flag & ~clr | set;
        !           400: 
        !           401:        if (val != NULL) {
        !           402:                if ((vp->flag&RDONLY))
        !           403:                        errorf("cannot set readonly %s\n", var);
        !           404:                if ((vp->flag&INTEGER))
        !           405:                        /* setstr should be able to handle this */
        !           406:                        (void)evaluate(var);
        !           407:                else
        !           408:                        setstr(vp, val);
        !           409:        }
        !           410: 
        !           411:        if ((vp->flag&EXPORT) && !(vp->flag&INTEGER) && vp->type == 0)
        !           412:                export(vp, (vp->flag&ISSET) ? vp->val.s : null);
        !           413: 
        !           414:        return vp;
        !           415: }
        !           416: 
        !           417: void
        !           418: unset(vp)
        !           419:        register struct tbl *vp;
        !           420: {
        !           421:        if ((vp->flag&ALLOC))
        !           422:                afree((Void*)vp->val.s, lastarea);
        !           423:        vp->flag &= ~ (ALLOC|ISSET);
        !           424: }
        !           425: 
        !           426: int
        !           427: isassign(s)
        !           428:        register char *s;
        !           429: {
        !           430:        if (!letter(*s))
        !           431:                return (0);
        !           432:        for (s++; *s != '='; s++)
        !           433:                if (*s == 0 || !letnum(*s))
        !           434:                        return (0);
        !           435:        return (1);
        !           436: }
        !           437: 
        !           438: /*
        !           439:  * Make the exported environment from the exported names in the dictionary.
        !           440:  */
        !           441: char **
        !           442: makenv()
        !           443: {
        !           444:        struct block *l = e.loc;
        !           445:        XPtrV env;
        !           446:        register struct tbl *vp, **vpp;
        !           447:        register int i;
        !           448: 
        !           449:        XPinit(env, 64);
        !           450:        for (l = e.loc; l != NULL; l = l->next)
        !           451:                for (vpp = l->vars.tbls, i = l->vars.size; --i >= 0; )
        !           452:                        if ((vp = *vpp++) != NULL
        !           453:                            && (vp->flag&(ISSET|EXPORT)) == (ISSET|EXPORT)) {
        !           454:                                register struct block *l2;
        !           455:                                register struct tbl *vp2;
        !           456:                                unsigned h = hash(vp->name);
        !           457: 
        !           458:                                lastarea = &l->area;
        !           459: 
        !           460:                                /* unexport any redefined instances */
        !           461:                                for (l2 = l->next; l2 != NULL; l2 = l2->next) {
        !           462:                                        vp2 = tsearch(&l2->vars, vp->name, h);
        !           463:                                        if (vp2 != NULL)
        !           464:                                                vp2->flag &= ~ EXPORT;
        !           465:                                }
        !           466:                                if ((vp->flag&INTEGER)) {
        !           467:                                        /* integer to string */
        !           468:                                        char *val;
        !           469:                                        val = strval(vp);
        !           470:                                        vp->flag &= ~ INTEGER;
        !           471:                                        setstr(vp, val);
        !           472:                                }
        !           473:                                XPput(env, vp->val.s);
        !           474:                        }
        !           475:        XPput(env, NULL);
        !           476:        return (char **) XPclose(env);
        !           477: }
        !           478: 
        !           479: /*
        !           480:  * handle special variables with side effects - PATH, SECONDS.
        !           481:  */
        !           482: 
        !           483: static int
        !           484: special(name)
        !           485:        register char * name;
        !           486: {
        !           487:        if (strcmp("PATH", name) == 0)
        !           488:                return V_PATH;
        !           489:        if (strcmp("IFS", name) == 0)
        !           490:                return V_IFS;
        !           491:        if (strcmp("SECONDS", name) == 0)
        !           492:                return V_SECONDS;
        !           493:        if (strcmp("OPTIND", name) == 0)
        !           494:                return V_OPTIND;
        !           495:        return V_NONE;
        !           496: }
        !           497: 
        !           498: extern time_t time();
        !           499: static time_t  seconds;                /* time SECONDS last set */
        !           500: 
        !           501: static void
        !           502: getspec(vp)
        !           503:        register struct tbl *vp;
        !           504: {
        !           505:        switch (special(vp->name)) {
        !           506:        case V_SECONDS:
        !           507:                vp->flag &= ~ SPECIAL;
        !           508:                setint(vp, time((time_t *)0) - seconds);
        !           509:                vp->flag |= SPECIAL;
        !           510:                break;
        !           511:        }
        !           512: }
        !           513: 
        !           514: static void
        !           515: setspec(vp)
        !           516:        register struct tbl *vp;
        !           517: {
        !           518:        switch (special(vp->name)) {
        !           519:          case V_PATH:
        !           520:                path = strval(vp);
        !           521:                flushcom(1);    /* clear tracked aliases */
        !           522:                break;
        !           523:          case V_IFS:
        !           524:                setctypes(strval(vp), C_IFS);
        !           525:                break;
        !           526:          case V_SECONDS:
        !           527:                seconds = time((time_t *)0);
        !           528:                break;
        !           529:          case V_OPTIND:
        !           530:                if (intval(vp) == 1)
        !           531:                        resetopts();
        !           532:                break;
        !           533:        }
        !           534: }
        !           535: 

unix.superglobalmegacorp.com

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