Annotation of coherent/d/bin/awk/awk5.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Awk - internal execution functions.
        !             3:  */
        !             4: 
        !             5: #include "awk.h"
        !             6: #include "y.tab.h"
        !             7: 
        !             8: FILE   *xoutput();
        !             9: 
        !            10: /*
        !            11:  * `print' directive.
        !            12:  * First argument is the NODE (or list) to print
        !            13:  * and the second is the output.
        !            14:  * Have to close pipes specially.
        !            15:  * The ALIST stuff should be generalised
        !            16:  * so that functions can get their arguments
        !            17:  * a little more easily.
        !            18:  */
        !            19: xprint(np, xp)
        !            20: register NODE *np;
        !            21: register NODE *xp;
        !            22: {
        !            23:        register FILE *ofp;
        !            24: 
        !            25:        ofp = xoutput(xp);
        !            26:        while (np != NULL) {
        !            27:                if (np->n_op == ALIST) {
        !            28:                        xp = np->n_O1;
        !            29:                        np = np->n_O2;
        !            30:                } else {
        !            31:                        xp = np;
        !            32:                        np = NULL;
        !            33:                }
        !            34:                xp = evalexpr(xp);
        !            35:                if (xp->t_flag & T_NUM) {
        !            36:                        if (xp->t_flag & T_INT)
        !            37:                                fprintf(ofp, OFMT, xp->t_INT); else
        !            38:                                fprintf(ofp, "%.6g", xp->t_FLOAT);
        !            39:                } else
        !            40:                        fprintf(ofp, "%s", xp->t_STRING);
        !            41:                if (np != NULL)
        !            42:                        fprintf(ofp, "%s", OFS);
        !            43:        }
        !            44:        fprintf(ofp, "%s", ORS);
        !            45:        fflush(ofp);
        !            46: }
        !            47: 
        !            48: /*
        !            49:  * `printf' directive.
        !            50:  * First argument is list, second
        !            51:  * is output.
        !            52:  * If third argument is non-NULL,
        !            53:  * it is used for sprintf rather than
        !            54:  * printf.
        !            55:  */
        !            56: xprintf(np, xp, sp)
        !            57: NODE *np;
        !            58: NODE *xp;
        !            59: STRING sp;
        !            60: {
        !            61:        NODE *nextarg();
        !            62:        int *pflist;
        !            63:        register CHAR *cp;
        !            64:        register int *pflp;
        !            65:        register int c;
        !            66:        register int i;
        !            67:        register FILE *ofp;
        !            68: 
        !            69:        pflp = pflist = (int *)xalloc(fnargs(np) * sizeof(double));
        !            70:        if (sp == NULL)
        !            71:                ofp = xoutput(xp); else
        !            72:                *sp = '\0';
        !            73:        i = 1;
        !            74:        *((CHAR **)pflp) = cp = evalstring(nextarg(np, i++));
        !            75:        bump(pflp, CHAR*);
        !            76:        for (;;) {
        !            77:                while ((c = *cp++)!='%' && c!='\0')
        !            78:                        ;
        !            79:                if (c == '\0')
        !            80:                        break;
        !            81:                if (*cp == '-')
        !            82:                        cp++;
        !            83:                if (*cp == '*') {
        !            84:                        *pflp++ = evalint(nextarg(np, i++));
        !            85:                        cp++;
        !            86:                } else
        !            87:                        while (isdigit(*cp))
        !            88:                                cp++;
        !            89:                if (*cp == '.') {
        !            90:                        cp++;
        !            91:                        if (*cp == '*') {
        !            92:                                *pflp++ = evalint(nextarg(np, i++));
        !            93:                                cp++;
        !            94:                        } else
        !            95:                                while (isdigit(*cp))
        !            96:                                        cp++;
        !            97:                }
        !            98:                if ((c = *cp++) == 'l')
        !            99:                        c = toupper(*cp++);
        !           100:                switch (c) {
        !           101:                case 'd':
        !           102:                case 'u':
        !           103:                case 'x':
        !           104:                case 'o':
        !           105:                        *pflp++ = evalint(nextarg(np, i++));
        !           106:                        break;
        !           107: 
        !           108:                case 'D':
        !           109:                case 'U':
        !           110:                case 'X':
        !           111:                case 'O':
        !           112:                        *((long *)pflp) = (long)evalint(nextarg(np, i++));
        !           113:                        bump(pflp, long);
        !           114:                        break;
        !           115: 
        !           116:                case 'e':
        !           117:                case 'f':
        !           118:                case 'g':
        !           119:                        *((double *)pflp) = (double)evalfloat(nextarg(np, i++));
        !           120:                        bump(pflp, double);
        !           121:                        break;
        !           122: 
        !           123:                case 'c':
        !           124:                        xp = evalexpr(nextarg(np, i++));
        !           125:                        if (xp->n_flag & T_NUM)
        !           126:                                *pflp++ = evalint(xp); else
        !           127:                                *pflp++ = *evalstring(xp);
        !           128:                        break;
        !           129: 
        !           130:                case 's':
        !           131:                        *((CHAR **)pflp) = evalstring(nextarg(np, i++));
        !           132:                        bump(pflp, CHAR*);
        !           133:                        break;
        !           134: 
        !           135:                case 'r':
        !           136:                        awkwarn("%%r not available in sprintf/printf");
        !           137:                        break;
        !           138:                }
        !           139:        }
        !           140:        if (sp == NULL) {
        !           141:                fprintf(ofp, "%r", pflist);
        !           142:                fflush(ofp);
        !           143:        } else
        !           144:                sprintf(sp, "%r", pflist);
        !           145:        free(pflist);
        !           146: }
        !           147: 
        !           148: /*
        !           149:   * Return the next argument for printf.
        !           150:  */
        !           151: static NODE *
        !           152: nextarg(anp, n)
        !           153: register NODE *anp;
        !           154: register int n;
        !           155: {
        !           156:        if ((anp = fargn(anp, n)) == NULL)
        !           157:                awkerr("Missing argument to printf/sprintf");
        !           158:        return (anp);
        !           159: }
        !           160: 
        !           161: /*
        !           162:  * Calculate the output
        !           163:  * stream for print or printf.
        !           164:  * This saves up names so that they
        !           165:  * don't get re-opened every time.
        !           166:  */
        !           167: FILE *
        !           168: xoutput(np)
        !           169: register NODE *np;
        !           170: {
        !           171:        register CHAR *s;
        !           172:        register OFILE *ofp;
        !           173:        register OFILE *ofslot;
        !           174: 
        !           175:        if (np == NULL)
        !           176:                return (stdout);
        !           177:        s = evalstring(np->n_O1);
        !           178:        ofslot = NULL;
        !           179:        for (ofp = files; ofp < endof(files); ofp++)
        !           180:                if (ofp->of_fp != NULL) {
        !           181:                        if (strcmp(ofp->of_name, s) == 0)
        !           182:                                return (ofp->of_fp);
        !           183:                } else
        !           184:                        ofslot = ofp;
        !           185:        if ((ofp = ofslot) == NULL)
        !           186:                awkerr("Too many output files or pipes");
        !           187:        ofp->of_flag = 0;
        !           188:        switch (np->n_op) {
        !           189:        case AFOUT:
        !           190:                if ((ofp->of_fp = fopen(s, "w")) == NULL)
        !           191:                        awkerr("Cannot open output `%s'", s);
        !           192:                break;
        !           193: 
        !           194:        case AFAPP:
        !           195:                if ((ofp->of_fp = fopen(s, "a")) == NULL)
        !           196:                        awkerr("Cannot open `%s' for append", s);
        !           197:                break;
        !           198: 
        !           199:        case AFPIPE:
        !           200: #ifndef GEMDOS
        !           201:                if ((ofp->of_fp = popen(s, "w")) == NULL)
        !           202: #endif
        !           203:                        awkerr("Cannot create pipe to `%s'", s);
        !           204:                ofp->of_flag = OFPIPE;
        !           205:                break;
        !           206: 
        !           207:        default:
        !           208:                awkerr("Bad output tree op %d", np->n_op);
        !           209:        }
        !           210:        ofp->of_name = xalloc(strlen(s) + sizeof(CHAR));
        !           211:        strcpy(ofp->of_name, s);
        !           212:        setbuf(ofp->of_fp, outbuf);
        !           213:        return (ofp->of_fp);
        !           214: }
        !           215: 
        !           216: /*
        !           217:  * Do the form: for (i in array) stat
        !           218:  * `var' is the index and `stat' the statement.
        !           219:  */
        !           220: xforin(var, array, stat)
        !           221: NODE *var;
        !           222: register NODE *array;
        !           223: NODE *stat;
        !           224: {
        !           225:        register CHAR *cp;
        !           226:        register TERM *tp;
        !           227:        register int i;
        !           228:        register int j;
        !           229: 
        !           230:        for (i=0; i<NHASH; i++)
        !           231:                for (tp = symtab[i]; tp != NULL; tp = tp->t_next)
        !           232:                        if (tp->t_ahval==array->t_hval && tp->t_flag&T_ARRAY
        !           233:                            && streq(tp->t_name, array->t_name)) {
        !           234:                                if ((j = setjmp(fwenv[fwlevel])) == ABREAK)
        !           235:                                        break;
        !           236:                                else if (j == ACONTIN)
        !           237:                                        continue;
        !           238:                                cp = tp->t_name;
        !           239:                                while (*cp++ != '\0')
        !           240:                                        ;
        !           241:                                xassign(var, snode(cp, 0));
        !           242:                                evalact(stat);
        !           243:                        }
        !           244: }
        !           245: 
        !           246: /*
        !           247:  * Return a node associated with
        !           248:  * an array element.
        !           249:  * `array' is the array identifier,
        !           250:  * and `index' is the index expression
        !           251:  * represented as a STRING.
        !           252:  */
        !           253: NODE *
        !           254: xarray(array, index)
        !           255: NODE *array;
        !           256: NODE *index;
        !           257: {
        !           258:        return (alookup(array->t_name, evalstring(index)));
        !           259: }
        !           260: 
        !           261: /*
        !           262:  * Extract the field given by the expression.
        !           263:  * A negative field number is
        !           264:  * considered to be from the end.
        !           265:  * The `asval' is non-NULL when
        !           266:  * the string is to be assigned to a field.
        !           267:  */
        !           268: NODE *
        !           269: xfield(i, asval)
        !           270: int i;
        !           271: STRING asval;
        !           272: {
        !           273:        CHAR *xfield1();
        !           274:        register CHAR *as, *s1, *s2;
        !           275:        register int c, i1;
        !           276:        register unsigned nb;
        !           277: 
        !           278:        if ((s1 = inline) == NULL) {
        !           279:                awkwarn("field, $%d, illegal in BEGIN or END", i);
        !           280:                return (snode(SNULL, 0));
        !           281:        }
        !           282:        if (i == 0) {
        !           283:                if (asval != NULL) {
        !           284:                        inline = xalloc(strlen(asval)+sizeof(CHAR));
        !           285:                        strcpy(inline, asval);
        !           286:                }
        !           287:                return (snode(inline, 0));
        !           288:        }
        !           289:        if (i < 0)
        !           290:                if ((i += (int)NF + 1) == 0)
        !           291:                        i = -1;
        !           292: 
        !           293:        i1 = i;
        !           294:        if (whitesw) {
        !           295:                do {
        !           296:                        while ((c = *s1) && FSMAP[c])
        !           297:                                s1++;
        !           298:                        if (!c || --i==0)
        !           299:                                break;
        !           300:                        while ((c = *s1) && !FSMAP[c])
        !           301:                                s1++;
        !           302:                } while (c);
        !           303:        } else {
        !           304:                do {
        !           305:                        if (!*s1 || --i==0)
        !           306:                                break;
        !           307:                        while ((c = *s1) && !FSMAP[c])
        !           308:                                s1++;
        !           309:                        if (FSMAP[*s1])
        !           310:                                s1++;
        !           311:                } while (c);
        !           312:        }
        !           313:        s2 = s1;
        !           314:        nb = sizeof(CHAR);
        !           315:        while ((c = *s2++)!='\0' && !FSMAP[c])
        !           316:                nb++;
        !           317:        s2--;
        !           318:        if (asval != NULL) {
        !           319:                /*
        !           320:                 * An attempt to set an arg past the end.
        !           321:                 */
        !           322:                if(0 < (i1 -= evalint(NFp))) {
        !           323:                        if (whitesw && (i1 > 1))
        !           324:                                awkwarn("Assignment to unbuildable field");
        !           325:                        /* remove trailing delimeters */
        !           326:                        while ((--s1 > inline) && FSMAP[*s1])
        !           327:                                ;
        !           328:                        s2 = ++s1;
        !           329:                        as = xalloc(strlen(asval) + i1 + 1);
        !           330:                        strcpy(as + i1, asval);
        !           331:                        memset(as, FS[0], i1);
        !           332: 
        !           333:                        inline = xfield1(inline, s1, as, s2, s2);
        !           334:                        free(as);
        !           335:                        return (snode(inline, 0));
        !           336:                }
        !           337:                inline = as = xfield1(inline, s1, asval, s2, s2+strlen(s2));
        !           338:                return (snode(inline, 0));
        !           339:        } else {
        !           340:                as = xalloc(nb);
        !           341:                while (s1 < s2)
        !           342:                        *as++ = *s1++;
        !           343:                *as++ = '\0';
        !           344:                as -= nb;
        !           345:        }
        !           346:        return (snode(as, T_ALLOC));
        !           347: }
        !           348: 
        !           349: /*
        !           350:  * Assignment of fields support.
        !           351:  * The arguments are:
        !           352:  * `f1', `f2', `middle', `e1', `e2'
        !           353:  * for the front start and stop, the middle
        !           354:  * and the end start and stop, respectively.
        !           355:  */
        !           356: CHAR *
        !           357: xfield1(f1, f2, middle, e1, e2)
        !           358: CHAR *f1, *f2;
        !           359: CHAR *middle;
        !           360: CHAR *e1, *e2;
        !           361: {
        !           362:        register CHAR *p1, *p2;
        !           363:        register CHAR *as;
        !           364: 
        !           365:        as = xalloc(f2-f1 + e2-e1 + strlen(middle) + sizeof(CHAR));
        !           366:        p1 = as;
        !           367:        p2 = f1;
        !           368:        while (p2 < f2)
        !           369:                *p1++ = *p2++;
        !           370:        p2 = middle;
        !           371:        while (*p2 != '\0')
        !           372:                *p1++ = *p2++;
        !           373:        p2 = e1;
        !           374:        while (p2 < e2)
        !           375:                *p1++ = *p2++;
        !           376:        *p1 = '\0';
        !           377:        return (as);
        !           378: }
        !           379: 
        !           380: /*
        !           381:  * String catenation in two nodes.
        !           382:  */
        !           383: NODE *
        !           384: xconc(n1, n2)
        !           385: register NODE *n1, *n2;
        !           386: {
        !           387:        register CHAR *ap;
        !           388:        register CHAR *cp1, *cp2;
        !           389:        register int n;
        !           390: 
        !           391:        n = strlen(ap = evalstring(n1)) + sizeof(CHAR);
        !           392:        if ((n1->t_un.t_flag & T_NUM) == 0) {
        !           393:                cp1 = xalloc(n);
        !           394:                strcpy(cp1, ap);
        !           395:        } else
        !           396:                cp1 = ap;
        !           397:        n += strlen(cp2 = evalstring(n2));
        !           398:        ap = xalloc(n);
        !           399:        strcpy(ap, cp1);
        !           400:        strcat(ap, cp2);
        !           401:        if ((n1->t_un.t_flag & T_NUM) == 0)
        !           402:                free(cp1);
        !           403:        return (snode(ap, T_ALLOC));
        !           404: }
        !           405: 
        !           406: /*
        !           407:  * Arithmetic operations --
        !           408:  *
        !           409:  * Numeric addition
        !           410:  */
        !           411: NODE *
        !           412: xadd(n1, n2)
        !           413: register NODE *n1, *n2;
        !           414: {
        !           415:        if (isfloat(n1) || isfloat(n2))
        !           416:                return (fnode(evalfloat(n1) + evalfloat(n2)));
        !           417:        return (inode(evalint(n1) + evalint(n2)));
        !           418: }
        !           419: 
        !           420: /*
        !           421:  * Subtraction -- actually a numeric operation.
        !           422:  */
        !           423: NODE *
        !           424: xsub(n1, n2)
        !           425: register NODE *n1, *n2;
        !           426: {
        !           427:        if (isfloat(n1) || isfloat(n2))
        !           428:                return (fnode(evalfloat(n1) - evalfloat(n2)));
        !           429:        return (inode(evalint(n1) - evalint(n2)));
        !           430: }
        !           431: 
        !           432: /*
        !           433:  * Multiplication
        !           434:  */
        !           435: NODE *
        !           436: xmul(n1, n2)
        !           437: register NODE *n1, *n2;
        !           438: {
        !           439:        if (isfloat(n1) || isfloat(n2))
        !           440:                return (fnode(evalfloat(n1) * evalfloat(n2)));
        !           441:        return (inode(evalint(n1) * evalint(n2)));
        !           442: }
        !           443: 
        !           444: /*
        !           445:  * Negation
        !           446:  */
        !           447: NODE *
        !           448: xneg(n1)
        !           449: register NODE *n1;
        !           450: {
        !           451:        if (isfloat(n1))
        !           452:                return (fnode(-evalfloat(n1)));
        !           453:        return (inode(-evalint(n1)));
        !           454: }
        !           455: 
        !           456: /*
        !           457:  * Division
        !           458:  * If either numeric is of internal FLOAT type,
        !           459:  * the division will be a float one, otherwise use
        !           460:  * INT division.
        !           461:  */
        !           462: NODE *
        !           463: xdiv(n1, n2)
        !           464: register NODE *n1, *n2;
        !           465: {
        !           466:        if (isfloat(n1) || isfloat(n2))
        !           467:                return (fnode(evalfloat(n1) / evalfloat(n2)));
        !           468:        return (inode(evalint(n1) / evalint(n2)));
        !           469: }
        !           470: 
        !           471: /*
        !           472:  * Modulus
        !           473:  * Same type conversion rule as for division.
        !           474:  */
        !           475: NODE *
        !           476: xmod(n1, n2)
        !           477: register NODE *n1, *n2;
        !           478: {
        !           479:        if (isfloat(n1) || isfloat(n2))
        !           480:                awkwarn("Modulus operator not allowed on floating point");
        !           481:        return (inode(evalint(n1) % evalint(n2)));
        !           482: }
        !           483: 
        !           484: /*
        !           485:  * Comparison operators --
        !           486:  * string or numeric comparison
        !           487:  * for equality or non-equality.
        !           488:  * The tricks come in conversions
        !           489:  * between FLOAT and INT.
        !           490:  * The nodes passed should not be evaluated
        !           491:  * beforehand so that checks for fields can
        !           492:  * be made as here fields are always considered
        !           493:  * as strings.
        !           494:  */
        !           495: NODE *
        !           496: xcmp(n1, n2, op)
        !           497: register NODE *n1, *n2;
        !           498: int op;
        !           499: {
        !           500:        register int result;
        !           501:        register int isnum = 0;
        !           502: 
        !           503:        if (n1->n_op != AFIELD)
        !           504:                isnum = isnumeric(n1 = evalexpr(n1));
        !           505:        else
        !           506:                n1 = evalexpr(n1);
        !           507:        if (n2->n_op != AFIELD)
        !           508:                isnum |= isnumeric(n2 = evalexpr(n2));
        !           509:        else
        !           510:                n2 = evalexpr(n2);
        !           511:        if (isnum) {
        !           512:                result = 0;
        !           513:                if (isfloat(n1) || isfloat(n2)) {
        !           514:                        register FLOAT f1, f2;
        !           515: 
        !           516:                        if ((f1 = evalfloat(n1)) > (f2 = evalfloat(n2)))
        !           517:                                result++;
        !           518:                        else if (f1 < f2)
        !           519:                                result--;
        !           520:                } else {
        !           521:                        register INT i1, i2;
        !           522: 
        !           523:                        if ((i1 = evalint(n1)) > (i2 = evalint(n2)))
        !           524:                                result++;
        !           525:                        else if (i1 < i2)
        !           526:                                result--;
        !           527:                }
        !           528:        } else if ((n1->t_flag & T_NUM)==0 && (n2->t_flag & T_NUM)==0)
        !           529:                result = strcmp(n1->t_STRING, n2->t_STRING);
        !           530:        else
        !           531:                result = strcmp(evalstring(n1), evalstring(n2));
        !           532:        switch (op) {
        !           533:        case AEQ:
        !           534:                result = result==0;
        !           535:                break;
        !           536: 
        !           537:        case ANE:
        !           538:                result = result!=0;
        !           539:                break;
        !           540: 
        !           541:        case AGT:
        !           542:                result = result>0;
        !           543:                break;
        !           544: 
        !           545:        case AGE:
        !           546:                result = result>=0;
        !           547:                break;
        !           548: 
        !           549:        case ALT:
        !           550:                result = result<0;
        !           551:                break;
        !           552: 
        !           553:        case ALE:
        !           554:                result = result<=0;
        !           555:                break;
        !           556:        }
        !           557:        return (inode((INT)result));
        !           558: }
        !           559: 
        !           560: /*
        !           561:  * Assignment
        !           562:  * The two nodes `l' and `r' are the left
        !           563:  * and right sides of the assignment,
        !           564:  * respectively.
        !           565:  */
        !           566: NODE *
        !           567: xassign(l, r)
        !           568: register NODE *l, *r;
        !           569: {
        !           570:        if (l->t_op == AFIELD)
        !           571:                return (xfield((int)evalint(l->n_O1), evalstring(r)));
        !           572:        else if (l->t_op == AARRAY)
        !           573:                l = xarray(l->n_O1, l->n_O2);
        !           574:        if ((l->t_flag & (T_ALLOC|T_NUM)) == T_ALLOC)
        !           575:                free(l->t_STRING);
        !           576:        l->t_flag &= ~(T_INT|T_NUM);
        !           577:        l->t_flag |= T_ALLOC|(r->t_flag & (T_INT|T_NUM));
        !           578:        if (r->t_flag & T_NUM)
        !           579:                if (r->t_flag & T_INT)
        !           580:                        l->t_INT = r->t_INT; else
        !           581:                        l->t_FLOAT = r->t_FLOAT;
        !           582:        else {
        !           583:                l->t_STRING = xalloc(strlen(r->t_STRING)+sizeof(CHAR));
        !           584:                strcpy(l->t_STRING, r->t_STRING);
        !           585:        }
        !           586:        if (l == FSp)
        !           587:                fsmapinit(evalstring(l));
        !           588:        return (l);
        !           589: }
        !           590: 
        !           591: /*
        !           592:  * Post increment -- return the old
        !           593:  * value before the increment of the
        !           594:  * node.
        !           595:  */
        !           596: NODE *
        !           597: xinca(np)
        !           598: register NODE *np;
        !           599: {
        !           600:        register NODE *rnp;
        !           601:        register NODE *enp;
        !           602: 
        !           603:        enp = evalexpr(np);
        !           604:        rnp = inode((INT)0);
        !           605:        xassign(rnp, enp);
        !           606:        xassign(np, xadd(enp, &xone));
        !           607:        return (rnp);
        !           608: }
        !           609: 
        !           610: /*
        !           611:  * Post decrement -- return the old value
        !           612:  * but increment the variable.
        !           613:  */
        !           614: NODE *
        !           615: xdeca(np)
        !           616: register NODE *np;
        !           617: {
        !           618:        register NODE *rnp;
        !           619:        register NODE *enp;
        !           620: 
        !           621:        enp = evalexpr(np);
        !           622:        rnp = inode((INT)0);
        !           623:        xassign(rnp, enp);
        !           624:        xassign(np, xsub(enp, &xone));
        !           625:        return (rnp);
        !           626: }

unix.superglobalmegacorp.com

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