* Alexander Polakov <polac...@gmail.com> [110324 15:48]:
> * Alexander Polakov <polac...@gmail.com> [110315 23:26]:
> > * Federico G. Schwindt <fg...@lodoss.net> [110315 17:38]:
> > > > I think I'm slightly confused as to you'd like fixed - do you mean that
> > > > one shouldn't need to escape a '[' if it's the first character? (note
> > > > that /bin/[ exists).  Else, can you clarify a bit more?  Thanks!
> > > 
> > >   correct, shouldn't need to escape a '[' if it's teh first character.
> > >   i do know of [, but command and file completion are two different 
> > > things.  see
> > > bash too.
> > 
> > I don't want to be defensive, but hey, how is bash relevant? [ is treated as
> > a globbing character, you know. Is it first character or not, ksh doesn't 
> > care,
> > it just tries to expand it.
> > 
> > Oh well, you can try expanding it and then - if it failed - escape it and
> > try again, like in the patch below. Bear in mind I didn't give it much 
> > thought, because I have a feeling it's not a good idea.
> 
> And just for the archives, a patch that really works as advertised
> (and using it for some time I feel like it *is* a good idea).

New version using toglob[] instead of str[] fixes double-escaping bug.
Tested by LEVAI Daniel and me.
Does anyone care? Woule be cool to have initial diff committed at least.

Index: bin/ksh/edit.c
===================================================================
RCS file: /cvs/src/bin/ksh/edit.c,v
retrieving revision 1.34
diff -u -r1.34 edit.c
--- bin/ksh/edit.c      20 May 2010 01:13:07 -0000      1.34
+++ bin/ksh/edit.c      5 Apr 2011 10:12:19 -0000
@@ -18,13 +18,14 @@
 #include <libgen.h>
 #include <sys/stat.h>
 
+#define ESCAPEDCHARS "\"#$&'()*;<=>?[\\`{|}"
 
 static void x_sigwinch(int);
 static volatile sig_atomic_t got_sigwinch;
 static void check_sigwinch(void);
 
-static int     x_file_glob(int, const char *, int, char ***);
-static int     x_command_glob(int, const char *, int, char ***);
+static int     x_file_glob(int, const char *, int, char ***, int);
+static int     x_command_glob(int, const char *, int, char ***, int);
 static int     x_locate_word(const char *, int, int, int *, int *);
 
 
@@ -344,10 +345,11 @@
  *     - returns number of matching strings
  */
 static int
-x_file_glob(int flags, const char *str, int slen, char ***wordsp)
+x_file_glob(int flags, const char *str, int slen, char ***wordsp, int 
canrecurse)
 {
        char *toglob;
        char **words;
+       char *estr;
        int nwords, i, idx, escaping;
        XPtrV w;
        struct source *s, *sold;
@@ -365,6 +367,11 @@
                        continue;
                }
 
+               /* specially escape escaped [ or $ or ` for globbing */
+               if (escaping && (toglob[i] == '[' ||
+                   toglob[i] == '$' || toglob[i] == '`'))
+                       toglob[idx++] = QCHAR;
+
                toglob[idx] = toglob[i];
                idx++;
                if (escaping) escaping = 0;
@@ -378,7 +385,7 @@
        s = pushs(SWSTR, ATEMP);
        s->start = s->str = toglob;
        source = s;
-       if (yylex(ONEWORD) != LWORD) {
+       if (yylex(ONEWORD|LQCHAR) != LWORD) {
                source = sold;
                internal_errorf(0, "fileglob: substitute error");
                return 0;
@@ -409,6 +416,24 @@
                        nwords = 0;
                }
        }
+
+       /* Globbing failed, do escaping and try again. */
+       if (!nwords && !words && canrecurse) {
+               slen = idx;
+               estr = alloc(2 * slen + 1, ATEMP);
+               idx = 0;
+               for(i = 0; i < slen; i++) {
+                       if (strchr(ESCAPEDCHARS, toglob[i]))
+                               estr[idx++] = '\\';
+                       estr[idx++] = toglob[i];
+               }
+               estr[idx] = '\0';
+               nwords = x_file_glob(flags, estr, idx, wordsp, !canrecurse);
+               afree(estr, ATEMP);
+               afree(toglob, ATEMP);
+               return nwords;
+       }
+
        afree(toglob, ATEMP);
 
        if (nwords) {
@@ -443,7 +468,7 @@
 }
 
 static int
-x_command_glob(int flags, const char *str, int slen, char ***wordsp)
+x_command_glob(int flags, const char *str, int slen, char ***wordsp, int 
canrecurse)
 {
        char *toglob;
        char *pat;
@@ -607,7 +632,7 @@
                return 0;
 
        nwords = (is_command ? x_command_glob : x_file_glob)(flags,
-           buf + *startp, len, &words);
+           buf + *startp, len, &words, 1);
        if (nwords == 0) {
                *wordsp = (char **) 0;
                return 0;
@@ -821,7 +846,7 @@
        int rval = 0;
 
        for (add = 0, wlen = len; wlen - add > 0; add++) {
-               if (strchr("\"#$&'()*;<=>?[\\]`{|}", s[add]) ||
+               if (strchr(ESCAPEDCHARS, s[add]) ||
                    strchr(ifs, s[add])) {
                        if (putbuf_func(s, add) != 0) {
                                rval = -1;
Index: bin/ksh/lex.c
===================================================================
RCS file: /cvs/src/bin/ksh/lex.c,v
retrieving revision 1.45
diff -u -r1.45 lex.c
--- bin/ksh/lex.c       9 Mar 2011 09:30:39 -0000       1.45
+++ bin/ksh/lex.c       5 Apr 2011 10:12:19 -0000
@@ -411,6 +411,13 @@
                                        }
                                }
                                break;
+                       case QCHAR:
+                               if (cf & LQCHAR) {
+                                       *wp++ = QCHAR;
+                                       *wp++ = getsc();
+                                       break;
+                               }
+                               /* FALLTHROUGH */
                        default:
                                *wp++ = CHAR, *wp++ = c;
                        }
Index: bin/ksh/lex.h
===================================================================
RCS file: /cvs/src/bin/ksh/lex.h,v
retrieving revision 1.11
diff -u -r1.11 lex.h
--- bin/ksh/lex.h       29 May 2006 18:22:24 -0000      1.11
+++ bin/ksh/lex.h       5 Apr 2011 10:12:19 -0000
@@ -113,6 +113,7 @@
 #define CMDWORD BIT(8)         /* parsing simple command (alias related) */
 #define HEREDELIM BIT(9)       /* parsing <<,<<- delimiter */
 #define HEREDOC BIT(10)                /* parsing heredoc */
+#define LQCHAR BIT(11)         /* source string contains QCHAR */
 
 #define        HERES   10              /* max << in line */
 

-- 
Alexander Polakov | plhk.ru

Reply via email to