Changeset 3449 for trunk/src/kash/eval.c


Ignore:
Timestamp:
Sep 13, 2020, 1:17:09 PM (5 years ago)
Author:
bird
Message:

kash: Eliminate the 'temp' node field in nfile so we can share node trees later.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kash/eval.c

    r3440 r3449  
    4141#endif
    4242
     43#include <assert.h>
     44#include <stddef.h>
    4345#include <stdlib.h>
    4446#include <stdio.h>
     
    103105STATIC void evalcase(shinstance *, union node *, int);
    104106STATIC void evalsubshell(shinstance *, union node *, int);
    105 STATIC void expredir(shinstance *, union node *);
    106 STATIC void expredircleanup(shinstance *, union node *);
     107STATIC unsigned expredir(shinstance *, union node *);
    107108STATIC void evalpipe(shinstance *, union node *);
    108109STATIC void evalcommand(shinstance *, union node *, int, struct backcmd *);
     
    247248                evaltree(psh, n->nbinary.ch2, flags);
    248249                break;
    249         case NREDIR:
    250                 expredir(psh, n->nredir.redirect);
     250        case NREDIR: {
     251                unsigned const oldfnames = expredir(psh, n->nredir.redirect);
    251252                redirect(psh, n->nredir.redirect, REDIR_PUSH);
    252253                evaltree(psh, n->nredir.n, flags);
    253254                popredir(psh);
    254                 expredircleanup(psh, n->nredir.redirect);
     255                expredircleanup(psh, oldfnames);
    255256                break;
     257        }
    256258        case NSUBSHELL:
    257259                evalsubshell(psh, n, flags);
     
    450452        struct job *jp;
    451453        int backgnd = (n->type == NBACKGND);
    452 
    453         expredir(psh, n->nredir.redirect);
     454        unsigned expfnamedepth;
     455
     456        expfnamedepth = expredir(psh, n->nredir.redirect);
    454457        INTOFF;
    455458        jp = makejob(psh, n, 1);
     
    474477        if (! backgnd)
    475478                psh->exitstatus = waitforjob(psh, jp);
     479        expredircleanup(psh, expfnamedepth);
    476480        INTON;
    477         expredircleanup(psh, n->nredir.redirect);
    478481}
    479482
     
    484487 */
    485488
    486 STATIC void
     489STATIC unsigned
    487490expredir(shinstance *psh, union node *n)
    488491{
    489492        union node *redir;
    490 
    491         for (redir = n ; redir ; redir = redir->nfile.next) {
     493        redirexpfnames *expfnames;
     494        unsigned i;
     495
     496        /* We typically end up here w/o redirections. */
     497        if (!n)
     498            return !(expfnames = psh->expfnames) ? 0 : expfnames->depth + 1;
     499
     500        /* Prepare a table for the expanded names. */
     501        i = 0;
     502        for (redir = n; redir ; redir = redir->nfile.next)
     503            i++;
     504        expfnames = stalloc(psh, offsetof(redirexpfnames, names) +  sizeof(expfnames->names[0]) * i);
     505        expfnames->count = i;
     506        TRACE2((psh, "expredir: %p: count=%u\n", expfnames, i));
     507
     508        /* Do the expansion. */
     509        for (redir = n, i = 0 ; redir ; redir = redir->nfile.next, i++) {
    492510                struct arglist fn;
    493511                fn.lastp = &fn.list;
     
    499517                case NAPPEND:
    500518                        expandarg(psh, redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
    501                         redir->nfile.expfname = fn.list->text;
     519                        expfnames->names[i] = fn.list->text;
    502520                        break;
    503521                case NFROMFD:
     
    507525                                fixredir(psh, redir, fn.list->text, 1);
    508526                        }
     527                        expfnames->names[i] = NULL;
    509528                        break;
    510                 }
    511         }
     529                default:
     530                        assert(0);
     531                        expfnames->names[i] = NULL;
     532                        break;
     533                }
     534        }
     535        assert(i == expfnames->count);
     536
     537        /* Do the linking at the end, as nesting happens when we expand backtick arguments. */
     538        expfnames->prev = psh->expfnames;
     539        psh->expfnames = expfnames;
     540        return expfnames->depth = psh->expfnames ? psh->expfnames->depth + 1 : 1;
    512541}
    513542
    514543STATIC void
    515 expredircleanup(shinstance *psh, union node *n)
    516 {
    517         for (; n ; n = n->nfile.next) {
    518                 struct arglist fn;
    519                 fn.lastp = &fn.list;
    520                 switch (n->type) {
    521                 case NFROMTO:
    522                 case NFROM:
    523                 case NTO:
    524                 case NCLOBBER:
    525                 case NAPPEND:
    526                         n->nfile.expfname = NULL;
    527                         break;
    528                 }
    529         }
     544expredircleanup(shinstance *psh, unsigned depth)
     545{
     546        redirexpfnames *expfnames = psh->expfnames;
     547        assert(expfnames == NULL ? depth == 0 : expfnames->depth == depth || expfnames->depth + 1 == depth);
     548        while (expfnames && expfnames->depth >= depth)
     549            expfnames = psh->expfnames = expfnames->prev;
    530550}
    531551
     
    11111131        struct strlist *sp;
    11121132        const char *path = pathval(psh);
     1133        unsigned expfnamedepth;
    11131134
    11141135        /* First expand the arguments. */
     
    11341155        *arglist.lastp = NULL;
    11351156
    1136         expredir(psh, cmd->ncmd.redirect);
     1157        expfnamedepth = expredir(psh, cmd->ncmd.redirect);
    11371158
    11381159        /* Now do the initial 'name=value' ones we skipped above */
     
    12541275                           &args, sizeof(args), evalcommand_setup_child);
    12551276                evalcommand_parent(psh, flags, args.lastarg, &args.smark, mode, jp,
    1256                                                    args.pip, backcmd);
     1277                                   args.pip, backcmd);
    12571278#else
    12581279                if (forkshell(psh, jp, cmd, mode) != 0) {
    12591280                        evalcommand_parent(psh, flags, args.lastarg, &args.smark, mode, jp,
    12601281                                                           args.pip, backcmd);
    1261                         expredircleanup(psh, cmd->ncmd.redirect);
     1282                        expredircleanup(psh, expfnamedepth);
    12621283                        return; /* at end of routine */
    12631284                }
     
    12701291                evalcommand_doit(psh, cmd, &args);
    12711292        }
    1272         expredircleanup(psh, cmd->ncmd.redirect);
     1293        expredircleanup(psh, expfnamedepth);
    12731294}
    12741295
Note: See TracChangeset for help on using the changeset viewer.