Annotation of coherent/a/usr/bob/korn/var.c, revision 1.1.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.