Commit a5c476d7 authored by jan.koester's avatar jan.koester
Browse files

fixed double quote

parent a13c43be
Loading
Loading
Loading
Loading
+79 −0
Changes for src/shell.cpp: 79 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -732,6 +732,85 @@ std::vector<std::string> fresh::tokenizeShellArgs(const std::string &segment){
                }
            };
            while(i<n && segment[i]!='"'){
                // "${...}" parameter expansion inside double quotes -- same
                // fix as the top-level scan above (see its own comment for
                // the full "$(...)  nested inside an operator's default
                // word" story): scanned here as one complete, brace-depth-
                // matched unit, with any nested "$(...)"/"`...`" resolved
                // via runCaptured() as the scan proceeds (honoring this
                // context's own double-quote escape rules -- \$, \`, \", \\
                // -- exactly like the plain-character accumulation just
                // below already does), BEFORE the standalone "$(cmd)"/
                // "`cmd`" branches just below ever get a chance to
                // intercept a nested substitution mid-scan and flushRaw() a
                // syntactically incomplete "${VAR:-" fragment on its own.
                if(segment[i]=='$' && i+1<n && segment[i+1]=='{'){
                    size_t j=i+2;
                    int depth=1;
                    std::string rawExpr;
                    while(j<n && depth>0){
                        char cj=segment[j];
                        if(cj=='{'){
                            ++depth;
                            rawExpr+=cj;
                            ++j;
                        }else if(cj=='}'){
                            --depth;
                            if(depth>0) rawExpr+=cj;
                            ++j;
                        }else if(cj=='$' && j+1<n && segment[j+1]=='(' &&
                                 !(j+2<n && segment[j+2]=='(')){
                            size_t k=j+2;
                            int pdepth=1;
                            while(k<n && pdepth>0){
                                if(segment[k]=='(') ++pdepth;
                                else if(segment[k]==')') --pdepth;
                                if(pdepth>0) ++k;
                            }
                            rawExpr+=Shell::instance().runCaptured(segment.substr(j+2,k-(j+2)));
                            j=(k<n) ? k+1 : k;
                        }else if(cj=='\\' && j+1<n && segment[j+1]=='`'){
                            rawExpr+='`';
                            j+=2;
                        }else if(cj=='`'){
                            size_t k=j+1;
                            std::string inner;
                            while(k<n && segment[k]!='`'){
                                if(segment[k]=='\\' && k+1<n &&
                                   (segment[k+1]=='`' || segment[k+1]=='$' ||
                                    segment[k+1]=='"' || segment[k+1]=='\\')){
                                    inner+=segment[k+1];
                                    k+=2;
                                    continue;
                                }
                                inner+=segment[k];
                                ++k;
                            }
                            rawExpr+=Shell::instance().runCaptured(inner);
                            j=(k<n) ? k+1 : k;
                        }else if(cj=='\\' && j+1<n && segment[j+1]=='$'){
                            rawExpr+=kLiteralDollarMarker;
                            j+=2;
                        }else if(cj=='\\' && j+1<n &&
                                 (segment[j+1]=='"' || segment[j+1]=='\\')){
                            rawExpr+=segment[j+1];
                            j+=2;
                        }else{
                            rawExpr+=cj;
                            ++j;
                        }
                    }
                    if(depth==0){
                        flushRaw();
                        dqResult+=fresh::Environment::instance().expand("${"+rawExpr+"}");
                        i=j;
                        continue;
                    }
                    // unterminated -- fall through, let '$' accumulate as
                    // an ordinary character below (same "not full parity"
                    // handling the top-level scan's own unterminated case
                    // already gets).
                }
                // "$(cmd)" inside double quotes -- NOT "$((expr))" (excluded
                // the same way the top-level scan excludes it, leaving it to
                // fall through to the plain accumulation below, so