Changeset 3449 for trunk/src


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.

Location:
trunk/src/kash
Files:
10 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
  • trunk/src/kash/generated/nodes.c

    r3443 r3449  
    276276            new->nfile.fd = n->nfile.fd;
    277277            new->nfile.next = copynode(n->nfile.next);
    278             new->nfile.expfname = NULL;
    279278            break;
    280279      case NTOFD:
  • trunk/src/kash/generated/nodes.h

    r3437 r3449  
    105105      union node *next;
    106106      union node *fname;
    107       char *expfname;
    108107};
    109108
  • trunk/src/kash/mknodes.sh

    r3443 r3449  
    200200                                string ) fn="nodesavestr(";;
    201201                                int ) fn=;;
    202                                 temp )  echo "      new->$f = 0;";;
     202                                temp )  echo "unexpected 'temp' node type" >&2; exit 2;;
    203203                                * ) continue;;
    204204                                esac
  • trunk/src/kash/nodetypes

    r3437 r3449  
    4545#       int - an integer
    4646#       other - any type that can be copied by assignment
    47 #       temp - a field that doesn't have to be copied when the node is copied
    4847# The last two types should be followed by the text of a C declaration for
    4948# the field.
     
    121120        next      nodeptr               # next redirection in list         (must match ndup)
    122121        fname     nodeptr               # file name, in a NARG node
    123         expfname  temp  char *expfname  # actual file name
    124122
    125123NTOFD ndup                      # fd<&dupfd
  • trunk/src/kash/parser.c

    r3440 r3449  
    11991199        union node *np;
    12001200        char fd = *out;
    1201         char dummy[   sizeof(struct nfile) >= sizeof(struct ndup)
    1202                    && sizeof(struct nfile) >= sizeof(struct nhere) ? 1 : 0];
     1201        char dummy[   sizeof(struct ndup) >= sizeof(struct nfile)
     1202                   && sizeof(struct ndup) >= sizeof(struct nhere) ? 1 : 0];
    12031203        (void)dummy;
    12041204
    1205         np = (union node *)stalloc(psh, sizeof (struct nfile));
    1206         np->nfile.expfname = NULL;
     1205        np = (union node *)stalloc(psh, sizeof (struct ndup));
    12071206        if (c == '>') {
    12081207                np->nfile.fd = 1;
     
    18991898                                ret->nfile.next      = copyparsetree(psh, src->nfile.next);
    19001899                                ret->nfile.fname     = copyparsetree(psh, src->nfile.fname);
    1901                                 /** @todo complicated, we should copy it in some contexts but no all. sigh.  */
    1902                                 ret->nfile.expfname  = stsavestr(psh, src->nfile.expfname);
    19031900                                break;
    19041901
  • trunk/src/kash/redir.c

    r3445 r3449  
    4343#include <sys/types.h>
    4444#include <limits.h>         /* PIPE_BUF */
     45#include <assert.h>
    4546#include <string.h>
    4647#include <errno.h>
     48#include <stddef.h>
    4749#include <stdlib.h>
    4850
     
    8890//int fd0_redirected = 0;
    8991
    90 STATIC void openredirect(shinstance *, union node *, char[10], int);
     92STATIC void openredirect(shinstance *, union node *, char[10], int, const char *);
    9193STATIC int openhere(shinstance *, union node *);
    9294
     
    114116        psh->fd0_redirected = inherit->fd0_redirected;
    115117    }
     118
     119    /* Copy the expanded redirection filenames (stack), but only the last entry
     120       as the subshell does not have the ability to unwind stack in the parent
     121       and therefore cannot get to the earlier redirection stuff: */
     122    if (inherit->expfnames)
     123    {
     124        redirexpfnames * const expfnamesrc = inherit->expfnames;
     125        unsigned i = expfnamesrc->count;
     126        redirexpfnames *dst = stalloc(psh, offsetof(redirexpfnames, names) + sizeof(dst->names[0]) * i);
     127        dst->count = i;
     128        dst->depth = 1;
     129        dst->prev = NULL;
     130        while (i-- > 0)
     131            dst->names[i] = stsavestr(psh, expfnamesrc->names[i]);
     132        psh->expfnames = dst;
     133    }
    116134}
    117135#endif /* !SH_FORKED_MODE */
     
    135153        int try;
    136154        char memory[10];        /* file descriptors to write to memory */
     155        unsigned idxexpfname;
    137156
    138157        for (i = 10 ; --i >= 0 ; )
     
    146165                psh->redirlist = sv;
    147166        }
    148         for (n = redir ; n ; n = n->nfile.next) {
     167        idxexpfname = 0;
     168        for (n = redir, idxexpfname = 0 ; n ; n = n->nfile.next, idxexpfname++) {
     169                assert(idxexpfname < psh->expfnames->count);
    149170                fd = n->nfile.fd;
    150171                try = 0;
     
    160181                                case EBADF:
    161182                                        if (!try) {
    162                                                 openredirect(psh, n, memory, flags);
     183                                                openredirect(psh, n, memory, flags, psh->expfnames->names[idxexpfname]);
    163184                                                try++;
    164185                                                goto again;
     
    182203                        psh->fd0_redirected++;
    183204                if (!try)
    184                         openredirect(psh, n, memory, flags);
    185         }
     205                        openredirect(psh, n, memory, flags, psh->expfnames->names[idxexpfname]);
     206        }
     207        assert(!redir || idxexpfname == psh->expfnames->count);
    186208        if (memory[1])
    187209                psh->out1 = &psh->memout;
     
    192214
    193215STATIC void
    194 openredirect(shinstance *psh, union node *redir, char memory[10], int flags)
     216openredirect(shinstance *psh, union node *redir, char memory[10], int flags, const char *fname)
    195217{
    196218        int fd = redir->nfile.fd;
    197         char *fname;
    198219        int f;
    199220        int oflags = O_WRONLY|O_CREAT|O_TRUNC;
     
    208229        switch (redir->nfile.type) {
    209230        case NFROM:
    210                 fname = redir->nfile.expfname;
    211231                if ((f = shfile_open(&psh->fdtab, fname, O_RDONLY, 0)) < 0)
    212232                        goto eopen;
    213233                break;
    214234        case NFROMTO:
    215                 fname = redir->nfile.expfname;
    216235                if ((f = shfile_open(&psh->fdtab, fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
    217236                        goto ecreate;
     
    222241                /* FALLTHROUGH */
    223242        case NCLOBBER:
    224                 fname = redir->nfile.expfname;
    225243                if ((f = shfile_open(&psh->fdtab, fname, oflags, 0666)) < 0)
    226244                        goto ecreate;
    227245                break;
    228246        case NAPPEND:
    229                 fname = redir->nfile.expfname;
    230247                if ((f = shfile_open(&psh->fdtab, fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
    231248                        goto ecreate;
  • trunk/src/kash/redir.h

    r3442 r3449  
    4646void popredir(struct shinstance *);
    4747int fd0_redirected_p(struct shinstance *);
     48struct redirexpfnames;
     49void expredircleanup(shinstance *, unsigned);
    4850void clearredir(struct shinstance *);
    4951int copyfd(struct shinstance *, int, int);
  • trunk/src/kash/shinstance.c

    r3447 r3449  
    437437    struct redirtab    *redirlist;
    438438    int                 fd0_redirected/* = 0*/;
    439 
     439#endif
     440    psh->expfnames = NULL; /* stack alloc */
     441
     442#if 0
    440443    /* show.c */
    441444    char                tracebuf[1024];
  • trunk/src/kash/shinstance.h

    r3447 r3449  
    131131        int inquotes;           /* search for nul bytes only */
    132132};
     133
     134/* redir.c / bird */
     135/**
     136 * This is a replacement for temporary node field nfile.expfname.
     137 * Uses stack allocator, created by expredir(), duplicated by
     138 * subshellinitredir() and popped (but not freed) by expredircleanup().
     139 */
     140typedef struct redirexpfnames
     141{
     142    struct redirexpfnames *prev;        /**< Previous record. */
     143    unsigned            depth;          /**< Nesting depth. */
     144    unsigned            count;          /**< Number of expanded filenames in the array. */
     145    char               *names[1];       /**< Variable size. */
     146} redirexpfnames;
    133147
    134148
     
    311325    struct redirtab    *redirlist;
    312326    int                 fd0_redirected/* = 0*/;
     327    redirexpfnames     *expfnames;      /**< Expanded filenames for current redirection setup. */
    313328
    314329    /* show.c */
Note: See TracChangeset for help on using the changeset viewer.