Annotation of coherent/d/bin/awk/awk5.c, revision 1.1.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.