Magellan Linux

Diff of /trunk/mkinitrd-magellan/klibc/usr/dash/expand.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1121 by niro, Fri Apr 24 18:32:46 2009 UTC revision 1122 by niro, Wed Aug 18 21:11:40 2010 UTC
# Line 42  Line 42 
42  #endif  #endif
43  #include <stdlib.h>  #include <stdlib.h>
44  #include <stdio.h>  #include <stdio.h>
45    #include <stdint.h>
46  #include <limits.h>  #include <limits.h>
47  #include <string.h>  #include <string.h>
 #if defined(__GLIBC__)  
 #if !defined(FNMATCH_BROKEN)  
48  #include <fnmatch.h>  #include <fnmatch.h>
49  #if !defined(GLOB_BROKEN)  #ifdef HAVE_GLOB
50  #include <glob.h>  #include <glob.h>
51  #endif  #endif
 #else  
52  #include <ctype.h>  #include <ctype.h>
 #endif  
 #endif  
53    
54  /*  /*
55   * Routines to expand arguments to commands.  We have to deal with   * Routines to expand arguments to commands.  We have to deal with
# Line 82  Line 78 
78   */   */
79  #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */  #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
80  #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */  #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */  
81  #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */  #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
82  #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */  #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
83    
84  /* Add CTLESC when necessary. */  /* Add CTLESC when necessary. */
85  #define QUOTES_ESC (EXP_FULL | EXP_CASE)  #define QUOTES_ESC (EXP_FULL | EXP_CASE | EXP_QPAT)
86  /* Do not skip NUL characters. */  /* Do not skip NUL characters. */
87  #define QUOTES_KEEPNUL EXP_TILDE  #define QUOTES_KEEPNUL EXP_TILDE
88    
# Line 116  static struct arglist exparg; Line 111  static struct arglist exparg;
111    
112  STATIC void argstr(char *, int);  STATIC void argstr(char *, int);
113  STATIC char *exptilde(char *, char *, int);  STATIC char *exptilde(char *, char *, int);
114  STATIC void expbackq(union node *, int, int);  STATIC void expbackq(union node *, int);
115  STATIC const char *subevalvar(char *, char *, int, int, int, int, int);  STATIC const char *subevalvar(char *, char *, int, int, int, int, int);
116  STATIC char *evalvar(char *, int);  STATIC char *evalvar(char *, int);
117  STATIC size_t strtodest(const char *, const char *, int);  STATIC size_t strtodest(const char *, const char *, int);
118  STATIC void memtodest(const char *, size_t, const char *, int);  STATIC void memtodest(const char *, size_t, const char *, int);
119  STATIC ssize_t varvalue(char *, int, int);  STATIC ssize_t varvalue(char *, int, int);
 STATIC void recordregion(int, int, int);  
 STATIC void removerecordregions(int);  
 STATIC void ifsbreakup(char *, struct arglist *);  
120  STATIC void ifsfree(void);  STATIC void ifsfree(void);
121  STATIC void expandmeta(struct strlist *, int);  STATIC void expandmeta(struct strlist *, int);
122  #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)  #ifdef HAVE_GLOB
123  STATIC void addglob(const glob_t *);  STATIC void addglob(const glob_t *);
124  #else  #else
125  STATIC void expmeta(char *, char *);  STATIC void expmeta(char *, char *);
 #endif  
 STATIC void addfname(char *);  
 #if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))  
126  STATIC struct strlist *expsort(struct strlist *);  STATIC struct strlist *expsort(struct strlist *);
127  STATIC struct strlist *msort(struct strlist *, int);  STATIC struct strlist *msort(struct strlist *, int);
128  #endif  #endif
129    STATIC void addfname(char *);
130  STATIC int patmatch(char *, const char *);  STATIC int patmatch(char *, const char *);
131  #if !defined(__GLIBC__) || defined(FNMATCH_BROKEN)  #ifndef HAVE_FNMATCH
132  STATIC int pmatch(const char *, const char *);  STATIC int pmatch(const char *, const char *);
133  #else  #else
134  #define pmatch(a, b) !fnmatch((a), (b), 0)  #define pmatch(a, b) !fnmatch((a), (b), 0)
135  #endif  #endif
136  STATIC int cvtnum(long);  STATIC int cvtnum(intmax_t);
137  STATIC size_t esclen(const char *, const char *);  STATIC size_t esclen(const char *, const char *);
138  STATIC char *scanleft(char *, char *, char *, char *, int, int);  STATIC char *scanleft(char *, char *, char *, char *, int, int);
139  STATIC char *scanright(char *, char *, char *, char *, int, int);  STATIC char *scanright(char *, char *, char *, char *, int, int);
# Line 158  STATIC void varunset(const char *, const Line 148  STATIC void varunset(const char *, const
148   */   */
149    
150  STATIC inline char *  STATIC inline char *
151  preglob(const char *pattern, int quoted, int flag) {  preglob(const char *pattern, int flag) {
152   flag |= RMESCAPE_GLOB;   flag |= RMESCAPE_GLOB;
  if (quoted) {  
  flag |= RMESCAPE_QUOTED;  
  }  
153   return _rmescapes((char *)pattern, flag);   return _rmescapes((char *)pattern, flag);
154  }  }
155    
# Line 190  static inline const char *getpwhome(cons Line 177  static inline const char *getpwhome(cons
177    
178    
179  /*  /*
  * Expand shell variables and backquotes inside a here document.  
  */  
   
 void  
 expandhere(union node *arg, int fd)  
 {  
  herefd = fd;  
  expandarg(arg, (struct arglist *)NULL, 0);  
  xwrite(fd, stackblock(), expdest - (char *)stackblock());  
 }  
   
   
 /*  
180   * Perform variable substitution and command substitution on an argument,   * Perform variable substitution and command substitution on an argument,
181   * placing the resulting list of arguments in arglist.  If EXP_FULL is true,   * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
182   * perform splitting and file name expansion.  When arglist is NULL, perform   * perform splitting and file name expansion.  When arglist is NULL, perform
# Line 271  argstr(char *p, int flag) Line 245  argstr(char *p, int flag)
245   CTLESC,   CTLESC,
246   CTLVAR,   CTLVAR,
247   CTLBACKQ,   CTLBACKQ,
  CTLBACKQ | CTLQUOTE,  
248   CTLENDARI,   CTLENDARI,
249   0   0
250   };   };
251   const char *reject = spclchars;   const char *reject = spclchars;
252   int c;   int c;
253   int quotes = flag & QUOTES_ESC;   int breakall = (flag & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
  int breakall = flag & EXP_WORD;  
254   int inquotes;   int inquotes;
255   size_t length;   size_t length;
256   int startloc;   int startloc;
# Line 296  argstr(char *p, int flag) Line 268  argstr(char *p, int flag)
268   flag &= ~EXP_TILDE;   flag &= ~EXP_TILDE;
269  tilde:  tilde:
270   q = p;   q = p;
  if (*q == (char)CTLESC && (flag & EXP_QWORD))  
  q++;  
271   if (*q == '~')   if (*q == '~')
272   p = exptilde(p, q, flag);   p = exptilde(p, q, flag);
273   }   }
# Line 348  start: Line 318  start:
318   case CTLENDVAR: /* ??? */   case CTLENDVAR: /* ??? */
319   goto breakloop;   goto breakloop;
320   case CTLQUOTEMARK:   case CTLQUOTEMARK:
321     inquotes ^= EXP_QUOTED;
322   /* "$@" syntax adherence hack */   /* "$@" syntax adherence hack */
323   if (   if (inquotes && !memcmp(p, dolatstr + 1,
324   !inquotes &&   DOLATSTRLEN - 1)) {
325   !memcmp(p, dolatstr, DOLATSTRLEN) &&   p = evalvar(p + 1, flag | inquotes) + 1;
  (p[4] == (char)CTLQUOTEMARK || (  
  p[4] == (char)CTLENDVAR &&  
  p[5] == (char)CTLQUOTEMARK  
  ))  
  ) {  
  p = evalvar(p + 1, flag) + 1;  
326   goto start;   goto start;
327   }   }
  inquotes = !inquotes;  
328  addquote:  addquote:
329   if (quotes) {   if (flag & QUOTES_ESC) {
330   p--;   p--;
331   length++;   length++;
332   startloc++;   startloc++;
# Line 371  addquote: Line 335  addquote:
335   case CTLESC:   case CTLESC:
336   startloc++;   startloc++;
337   length++;   length++;
338    
339     /*
340     * Quoted parameter expansion pattern: remove quote
341     * unless inside inner quotes or we have a literal
342     * backslash.
343     */
344     if (((flag | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
345        EXP_QPAT && *p != '\\')
346     break;
347    
348   goto addquote;   goto addquote;
349   case CTLVAR:   case CTLVAR:
350   p = evalvar(p, flag);   p = evalvar(p, flag | inquotes);
351   goto start;   goto start;
352   case CTLBACKQ:   case CTLBACKQ:
353   c = 0;   expbackq(argbackq->n, flag | inquotes);
  case CTLBACKQ|CTLQUOTE:  
  expbackq(argbackq->n, c, quotes);  
354   argbackq = argbackq->next;   argbackq = argbackq->next;
355   goto start;   goto start;
356   case CTLENDARI:   case CTLENDARI:
357   p--;   p--;
358   expari(quotes);   expari(flag | inquotes);
359   goto start;   goto start;
360   }   }
361   }   }
# Line 437  lose: Line 409  lose:
409  }  }
410    
411    
412  STATIC void  void
413  removerecordregions(int endoff)  removerecordregions(int endoff)
414  {  {
415   if (ifslastp == NULL)   if (ifslastp == NULL)
# Line 482  removerecordregions(int endoff) Line 454  removerecordregions(int endoff)
454   * evaluate, place result in (backed up) result, adjust string position.   * evaluate, place result in (backed up) result, adjust string position.
455   */   */
456  void  void
457  expari(int quotes)  expari(int flag)
458  {  {
459     struct stackmark sm;
460   char *p, *start;   char *p, *start;
461   int begoff;   int begoff;
  int flag;  
462   int len;   int len;
463     intmax_t result;
464    
465   /* ifsfree(); */   /* ifsfree(); */
466    
# Line 497  expari(int quotes) Line 470  expari(int quotes)
470   * start of arithmetic.   * start of arithmetic.
471   */   */
472   start = stackblock();   start = stackblock();
473   p = expdest - 1;   p = expdest;
474   *p = '\0';   pushstackmark(&sm, p - start);
475     *--p = '\0';
476   p--;   p--;
477   do {   do {
478   int esc;   int esc;
# Line 524  expari(int quotes) Line 498  expari(int quotes)
498    
499   removerecordregions(begoff);   removerecordregions(begoff);
500    
  flag = p[1];  
   
501   expdest = p;   expdest = p;
502    
503   if (quotes)   if (likely(flag & QUOTES_ESC))
504   rmescapes(p + 2);   rmescapes(p + 1);
505    
506     result = arith(p + 1);
507     popstackmark(&sm);
508    
509   len = cvtnum(arith(p + 2));   len = cvtnum(result);
510    
511   if (flag != '"')   if (likely(!(flag & EXP_QUOTED)))
512   recordregion(begoff, begoff + len, 0);   recordregion(begoff, begoff + len, 0);
513  }  }
514    
# Line 543  expari(int quotes) Line 518  expari(int quotes)
518   */   */
519    
520  STATIC void  STATIC void
521  expbackq(union node *cmd, int quoted, int quotes)  expbackq(union node *cmd, int flag)
522  {  {
523   struct backcmd in;   struct backcmd in;
524   int i;   int i;
# Line 551  expbackq(union node *cmd, int quoted, in Line 526  expbackq(union node *cmd, int quoted, in
526   char *p;   char *p;
527   char *dest;   char *dest;
528   int startloc;   int startloc;
529   char const *syntax = quoted? DQSYNTAX : BASESYNTAX;   char const *syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
530   struct stackmark smark;   struct stackmark smark;
531    
532   INTOFF;   INTOFF;
533   setstackmark(&smark);   startloc = expdest - (char *)stackblock();
534   dest = expdest;   pushstackmark(&smark, startloc);
  startloc = dest - (char *)stackblock();  
  grabstackstr(dest);  
535   evalbackcmd(cmd, (struct backcmd *) &in);   evalbackcmd(cmd, (struct backcmd *) &in);
536   popstackmark(&smark);   popstackmark(&smark);
537    
# Line 567  expbackq(union node *cmd, int quoted, in Line 540  expbackq(union node *cmd, int quoted, in
540   if (i == 0)   if (i == 0)
541   goto read;   goto read;
542   for (;;) {   for (;;) {
543   memtodest(p, i, syntax, quotes);   memtodest(p, i, syntax, flag & QUOTES_ESC);
544  read:  read:
545   if (in.fd < 0)   if (in.fd < 0)
546   break;   break;
# Line 594  read: Line 567  read:
567   STUNPUTC(dest);   STUNPUTC(dest);
568   expdest = dest;   expdest = dest;
569    
570   if (quoted == 0)   if (!(flag & EXP_QUOTED))
571   recordregion(startloc, dest - (char *)stackblock(), 0);   recordregion(startloc, dest - (char *)stackblock(), 0);
572   TRACE(("evalbackq: size=%d: \"%.*s\"\n",   TRACE(("evalbackq: size=%d: \"%.*s\"\n",
573   (dest - (char *)stackblock()) - startloc,   (dest - (char *)stackblock()) - startloc,
# Line 671  scanright( Line 644  scanright(
644  }  }
645    
646  STATIC const char *  STATIC const char *
647  subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)  subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int flag)
648  {  {
649     int quotes = flag & QUOTES_ESC;
650   char *startp;   char *startp;
651   char *loc;   char *loc;
  int saveherefd = herefd;  
652   struct nodelist *saveargbackq = argbackq;   struct nodelist *saveargbackq = argbackq;
653   int amount;   int amount;
654   char *rmesc, *rmescend;   char *rmesc, *rmescend;
655   int zero;   int zero;
656   char *(*scan)(char *, char *, char *, char *, int , int);   char *(*scan)(char *, char *, char *, char *, int , int);
657    
658   herefd = -1;   argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
659   argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);         (flag & EXP_QUOTED ? EXP_QPAT : EXP_CASE) : 0));
660   STPUTC('\0', expdest);   STPUTC('\0', expdest);
  herefd = saveherefd;  
661   argbackq = saveargbackq;   argbackq = saveargbackq;
662   startp = stackblock() + startloc;   startp = stackblock() + startloc;
663    
# Line 718  subevalvar(char *p, char *str, int strlo Line 690  subevalvar(char *p, char *str, int strlo
690   }   }
691   rmescend--;   rmescend--;
692   str = stackblock() + strloc;   str = stackblock() + strloc;
693   preglob(str, varflags & VSQUOTE, 0);   preglob(str, 0);
694    
695   /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */   /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
696   zero = subtype >> 1;   zero = subtype >> 1;
# Line 754  evalvar(char *p, int flag) Line 726  evalvar(char *p, int flag)
726   int startloc;   int startloc;
727   ssize_t varlen;   ssize_t varlen;
728   int easy;   int easy;
  int quotes;  
729   int quoted;   int quoted;
730    
  quotes = flag & QUOTES_ESC;  
731   varflags = *p++;   varflags = *p++;
732   subtype = varflags & VSTYPE;   subtype = varflags & VSTYPE;
733   quoted = varflags & VSQUOTE;  
734     if (!subtype)
735     sh_error("Bad substitution");
736    
737     quoted = flag & EXP_QUOTED;
738   var = p;   var = p;
739   easy = (!quoted || (*var == '@' && shellparam.nparam));   easy = (!quoted || (*var == '@' && shellparam.nparam));
740   startloc = expdest - (char *)stackblock();   startloc = expdest - (char *)stackblock();
# Line 779  again: Line 753  again:
753   if (subtype == VSMINUS) {   if (subtype == VSMINUS) {
754  vsplus:  vsplus:
755   if (varlen < 0) {   if (varlen < 0) {
756   argstr(   argstr(p, flag | EXP_TILDE | EXP_WORD);
  p, flag | EXP_TILDE |  
  (quoted ?  EXP_QWORD : EXP_WORD)  
  );  
757   goto end;   goto end;
758   }   }
759   if (easy)   if (easy)
# Line 793  vsplus: Line 764  vsplus:
764   if (subtype == VSASSIGN || subtype == VSQUESTION) {   if (subtype == VSASSIGN || subtype == VSQUESTION) {
765   if (varlen < 0) {   if (varlen < 0) {
766   if (subevalvar(p, var, 0, subtype, startloc,   if (subevalvar(p, var, 0, subtype, startloc,
767         varflags, 0)) {         varflags, flag & ~QUOTES_ESC)) {
768   varflags &= ~VSNUL;   varflags &= ~VSNUL;
769   /*   /*
770   * Remove any recorded regions beyond   * Remove any recorded regions beyond
# Line 845  record: Line 816  record:
816   STPUTC('\0', expdest);   STPUTC('\0', expdest);
817   patloc = expdest - (char *)stackblock();   patloc = expdest - (char *)stackblock();
818   if (subevalvar(p, NULL, patloc, subtype,   if (subevalvar(p, NULL, patloc, subtype,
819         startloc, varflags, quotes) == 0) {         startloc, varflags, flag) == 0) {
820   int amount = expdest - (   int amount = expdest - (
821   (char *)stackblock() + patloc - 1   (char *)stackblock() + patloc - 1
822   );   );
# Line 862  end: Line 833  end:
833   for (;;) {   for (;;) {
834   if ((c = (signed char)*p++) == CTLESC)   if ((c = (signed char)*p++) == CTLESC)
835   p++;   p++;
836   else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {   else if (c == CTLBACKQ) {
837   if (varlen >= 0)   if (varlen >= 0)
838   argbackq = argbackq->next;   argbackq = argbackq->next;
839   } else if (c == CTLVAR) {   } else if (c == CTLVAR) {
# Line 895  memtodest(const char *p, size_t len, con Line 866  memtodest(const char *p, size_t len, con
866   int c = (signed char)*p++;   int c = (signed char)*p++;
867   if (c) {   if (c) {
868   if ((quotes & QUOTES_ESC) &&   if ((quotes & QUOTES_ESC) &&
869      (syntax[c] == CCTL || syntax[c] == CBACK))      ((syntax[c] == CCTL) ||
870         (((quotes & EXP_FULL) || syntax != BASESYNTAX) &&
871          syntax[c] == CBACK)))
872   USTPUTC(CTLESC, q);   USTPUTC(CTLESC, q);
873   } else if (!(quotes & QUOTES_KEEPNUL))   } else if (!(quotes & QUOTES_KEEPNUL))
874   continue;   continue;
# Line 933  varvalue(char *name, int varflags, int f Line 906  varvalue(char *name, int varflags, int f
906   char sepc;   char sepc;
907   char **ap;   char **ap;
908   char const *syntax;   char const *syntax;
909   int quoted = varflags & VSQUOTE;   int quoted = flags & EXP_QUOTED;
910   int subtype = varflags & VSTYPE;   int subtype = varflags & VSTYPE;
911   int discard = subtype == VSPLUS || subtype == VSLENGTH;   int discard = subtype == VSPLUS || subtype == VSLENGTH;
912   int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;   int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
# Line 1025  value: Line 998  value:
998   * string for IFS characters.   * string for IFS characters.
999   */   */
1000    
1001  STATIC void  void
1002  recordregion(int start, int end, int nulonly)  recordregion(int start, int end, int nulonly)
1003  {  {
1004   struct ifsregion *ifsp;   struct ifsregion *ifsp;
# Line 1052  recordregion(int start, int end, int nul Line 1025  recordregion(int start, int end, int nul
1025   * strings to the argument list.  The regions of the string to be   * strings to the argument list.  The regions of the string to be
1026   * searched for IFS characters have been stored by recordregion.   * searched for IFS characters have been stored by recordregion.
1027   */   */
1028  STATIC void  void
1029  ifsbreakup(char *string, struct arglist *arglist)  ifsbreakup(char *string, struct arglist *arglist)
1030  {  {
1031   struct ifsregion *ifsp;   struct ifsregion *ifsp;
# Line 1162  ifsfree(void) Line 1135  ifsfree(void)
1135   * should be escapes.  The results are stored in the list exparg.   * should be escapes.  The results are stored in the list exparg.
1136   */   */
1137    
1138  #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)  #ifdef HAVE_GLOB
1139  STATIC void  STATIC void
1140  expandmeta(str, flag)  expandmeta(str, flag)
1141   struct strlist *str;   struct strlist *str;
# Line 1178  expandmeta(str, flag) Line 1151  expandmeta(str, flag)
1151   if (fflag)   if (fflag)
1152   goto nometa;   goto nometa;
1153   INTOFF;   INTOFF;
1154   p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);   p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
1155   i = glob(p, GLOB_NOMAGIC, 0, &pglob);   i = glob(p, GLOB_NOMAGIC, 0, &pglob);
1156   if (p != str->text)   if (p != str->text)
1157   ckfree(p);   ckfree(p);
# Line 1223  addglob(pglob) Line 1196  addglob(pglob)
1196  }  }
1197    
1198    
1199  #else /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */  #else /* HAVE_GLOB */
1200  STATIC char *expdir;  STATIC char *expdir;
1201    
1202    
# Line 1247  expandmeta(struct strlist *str, int flag Line 1220  expandmeta(struct strlist *str, int flag
1220   savelastp = exparg.lastp;   savelastp = exparg.lastp;
1221    
1222   INTOFF;   INTOFF;
1223   p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);   p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
1224   {   {
1225   int i = strlen(str->text);   int i = strlen(str->text);
1226   expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */   expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
# Line 1295  expmeta(char *enddir, char *name) Line 1268  expmeta(char *enddir, char *name)
1268   struct dirent *dp;   struct dirent *dp;
1269   int atend;   int atend;
1270   int matchdot;   int matchdot;
1271     int esc;
1272    
1273   metaflag = 0;   metaflag = 0;
1274   start = name;   start = name;
1275   for (p = name; *p; p++) {   for (p = name; esc = 0, *p; p += esc + 1) {
1276   if (*p == '*' || *p == '?')   if (*p == '*' || *p == '?')
1277   metaflag = 1;   metaflag = 1;
1278   else if (*p == '[') {   else if (*p == '[') {
# Line 1315  expmeta(char *enddir, char *name) Line 1289  expmeta(char *enddir, char *name)
1289   break;   break;
1290   }   }
1291   }   }
1292   } else if (*p == '\\')   } else {
1293   p++;   if (*p == '\\')
1294   else if (*p == '/') {   esc++;
1295   if (metaflag)   if (p[esc] == '/') {
1296   goto out;   if (metaflag)
1297   start = p + 1;   break;
1298     start = p + esc + 1;
1299     }
1300   }   }
1301   }   }
 out:  
1302   if (metaflag == 0) { /* we've reached the end of the file name */   if (metaflag == 0) { /* we've reached the end of the file name */
1303   if (enddir != expdir)   if (enddir != expdir)
1304   metaflag++;   metaflag++;
# Line 1362  out: Line 1337  out:
1337   atend = 1;   atend = 1;
1338   } else {   } else {
1339   atend = 0;   atend = 0;
1340   *endname++ = '\0';   *endname = '\0';
1341     endname += esc + 1;
1342   }   }
1343   matchdot = 0;   matchdot = 0;
1344   p = start;   p = start;
# Line 1388  out: Line 1364  out:
1364   }   }
1365   closedir(dirp);   closedir(dirp);
1366   if (! atend)   if (! atend)
1367   endname[-1] = '/';   endname[-esc - 1] = esc ? '\\' : '/';
1368  }  }
1369  #endif /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */  #endif /* HAVE_GLOB */
1370    
1371    
1372  /*  /*
# Line 1409  addfname(char *name) Line 1385  addfname(char *name)
1385  }  }
1386    
1387    
1388  #if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))  #ifndef HAVE_GLOB
1389  /*  /*
1390   * Sort the results of file name expansion.  It calculates the number of   * Sort the results of file name expansion.  It calculates the number of
1391   * strings to sort and then calls msort (short for merge sort) to do the   * strings to sort and then calls msort (short for merge sort) to do the
# Line 1478  msort(struct strlist *list, int len) Line 1454  msort(struct strlist *list, int len)
1454  STATIC inline int  STATIC inline int
1455  patmatch(char *pattern, const char *string)  patmatch(char *pattern, const char *string)
1456  {  {
1457   return pmatch(preglob(pattern, 0, 0), string);   return pmatch(preglob(pattern, 0), string);
1458  }  }
1459    
1460    
1461  #if !defined(__GLIBC__) || defined(FNMATCH_BROKEN)  #ifndef HAVE_FNMATCH
1462  STATIC int ccmatch(const char *p, int chr, const char **r)  STATIC int ccmatch(const char *p, int chr, const char **r)
1463  {  {
1464   static const struct class {   static const struct class {
# Line 1643  _rmescapes(char *str, int flag) Line 1619  _rmescapes(char *str, int flag)
1619   size_t fulllen = len + strlen(p) + 1;   size_t fulllen = len + strlen(p) + 1;
1620    
1621   if (flag & RMESCAPE_GROW) {   if (flag & RMESCAPE_GROW) {
1622     int strloc = str - (char *)stackblock();
1623    
1624   r = makestrspace(fulllen, expdest);   r = makestrspace(fulllen, expdest);
1625     str = (char *)stackblock() + strloc;
1626     p = str + len;
1627   } else if (flag & RMESCAPE_HEAP) {   } else if (flag & RMESCAPE_HEAP) {
1628   r = ckmalloc(fulllen);   r = ckmalloc(fulllen);
1629   } else {   } else {
# Line 1654  _rmescapes(char *str, int flag) Line 1634  _rmescapes(char *str, int flag)
1634   q = mempcpy(q, str, len);   q = mempcpy(q, str, len);
1635   }   }
1636   }   }
1637   inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;   inquotes = 0;
1638   globbing = flag & RMESCAPE_GLOB;   globbing = flag & RMESCAPE_GLOB;
1639   notescaped = globbing;   notescaped = globbing;
1640   while (*p) {   while (*p) {
# Line 1664  _rmescapes(char *str, int flag) Line 1644  _rmescapes(char *str, int flag)
1644   notescaped = globbing;   notescaped = globbing;
1645   continue;   continue;
1646   }   }
  if (*p == '\\') {  
  /* naked back slash */  
  notescaped = 0;  
  goto copy;  
  }  
1647   if (*p == (char)CTLESC) {   if (*p == (char)CTLESC) {
1648   p++;   p++;
1649   if (notescaped && inquotes && *p != '/') {   if (notescaped)
1650   *q++ = '\\';   *q++ = '\\';
1651   }   } else if (*p == '\\' && !inquotes) {
1652     /* naked back slash */
1653     notescaped = 0;
1654     goto copy;
1655   }   }
1656   notescaped = globbing;   notescaped = globbing;
1657  copy:  copy:
# Line 1715  casematch(union node *pattern, char *val Line 1693  casematch(union node *pattern, char *val
1693   */   */
1694    
1695  STATIC int  STATIC int
1696  cvtnum(long num)  cvtnum(intmax_t num)
1697  {  {
1698   int len;   int len = max_int_length(sizeof(num));
1699    
1700   expdest = makestrspace(32, expdest);   expdest = makestrspace(len, expdest);
1701   len = fmtstr(expdest, 32, "%ld", num);   len = fmtstr(expdest, len, "%jd", num);
1702   STADJUST(len, expdest);   STADJUST(len, expdest);
1703   return len;   return len;
1704  }  }

Legend:
Removed from v.1121  
changed lines
  Added in v.1122