match.patch 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. --- match.c 2011-09-07 23:00:58.037644003 +0200
  2. +++ match.final.c 2011-09-07 23:32:19.433644002 +0200
  3. @@ -27,16 +27,14 @@
  4. ---------------------------------------------------------------------------
  5. - Copyright on recmatch() from Zip's util.c (although recmatch() was almost
  6. - certainly written by Mark Adler...ask me how I can tell :-) ):
  7. + Copyright on recmatch() from Zip's util.c
  8. + Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
  9. - Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly,
  10. - Kai Uwe Rommel and Igor Mandrichenko.
  11. + See the accompanying file LICENSE, version 2004-May-22 or later
  12. + for terms of use.
  13. + If, for some reason, both of these files are missing, the Info-ZIP license
  14. + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
  15. - Permission is granted to any individual or institution to use, copy,
  16. - or redistribute this software so long as all of the original files are
  17. - included unmodified, that it is not sold for profit, and that this copy-
  18. - right notice is retained.
  19. ---------------------------------------------------------------------------
  20. @@ -53,7 +51,7 @@
  21. A set is composed of characters or ranges; a range looks like ``character
  22. hyphen character'' (as in 0-9 or A-Z). [0-9a-zA-Z_] is the minimal set of
  23. - characters allowed in the [..] pattern construct. Other characters are
  24. + characters ALlowed in the [..] pattern construct. Other characters are
  25. allowed (i.e., 8-bit characters) if your system will support them.
  26. To suppress the special syntactic significance of any of ``[]*?!^-\'', in-
  27. @@ -101,8 +99,32 @@
  28. # define WILDCHAR '?'
  29. # define BEG_RANGE '['
  30. # define END_RANGE ']'
  31. +# define WILDCHR_SINGLE '?'
  32. +# define DIRSEP_CHR '/'
  33. +# define WILDCHR_MULTI '*'
  34. #endif
  35. +#ifdef WILD_STOP_AT_DIR
  36. + int wild_stop_at_dir = 1; /* default wildcards do not include / in matches */
  37. +#else
  38. + int wild_stop_at_dir = 0; /* default wildcards do include / in matches */
  39. +#endif
  40. +
  41. +
  42. +
  43. +/*
  44. + * case mapping functions. case_map is used to ignore case in comparisons,
  45. + * to_up is used to force upper case even on Unix (for dosify option).
  46. + */
  47. +#ifdef USE_CASE_MAP
  48. +# define case_map(c) upper[(c) & 0xff]
  49. +# define to_up(c) upper[(c) & 0xff]
  50. +#else
  51. +# define case_map(c) (c)
  52. +# define to_up(c) ((c) >= 'a' && (c) <= 'z' ? (c)-'a'+'A' : (c))
  53. +#endif /* USE_CASE_MAP */
  54. +
  55. +
  56. #if 0 /* GRR: add this to unzip.h someday... */
  57. #if !(defined(MSDOS) && defined(DOSWILD))
  58. #ifdef WILD_STOP_AT_DIR
  59. @@ -114,8 +136,8 @@
  60. int ignore_case __WDLPRO));
  61. #endif
  62. #endif /* 0 */
  63. -static int recmatch OF((ZCONST uch *pattern, ZCONST uch *string,
  64. - int ignore_case __WDLPRO));
  65. +static int recmatch OF((ZCONST char *, ZCONST char *,
  66. + int));
  67. static char *isshexp OF((ZCONST char *p));
  68. static int namecmp OF((ZCONST char *s1, ZCONST char *s2));
  69. @@ -154,192 +176,236 @@
  70. }
  71. dospattern[j-1] = '\0'; /* nuke the end "." */
  72. }
  73. - j = recmatch((uch *)dospattern, (uch *)string, ignore_case __WDL);
  74. + j = recmatch(dospattern, string, ignore_case);
  75. free(dospattern);
  76. return j == 1;
  77. } else
  78. #endif /* MSDOS && DOSWILD */
  79. - return recmatch((uch *)pattern, (uch *)string, ignore_case __WDL) == 1;
  80. + return recmatch(pattern, string, ignore_case) == 1;
  81. }
  82. -static int recmatch(p, s, ic __WDL)
  83. - ZCONST uch *p; /* sh pattern to match */
  84. - ZCONST uch *s; /* string to which to match it */
  85. - int ic; /* true for case insensitivity */
  86. - __WDLDEF /* directory sepchar for WildStopAtDir mode, or 0 */
  87. +static int recmatch(p, s, cs)
  88. +ZCONST char *p; /* sh pattern to match */
  89. +ZCONST char *s; /* string to match it to */
  90. +int cs; /* flag: force case-sensitive matching */
  91. /* Recursively compare the sh pattern p with the string s and return 1 if
  92. - * they match, and 0 or 2 if they don't or if there is a syntax error in the
  93. - * pattern. This routine recurses on itself no more deeply than the number
  94. - * of characters in the pattern. */
  95. + they match, and 0 or 2 if they don't or if there is a syntax error in the
  96. + pattern. This routine recurses on itself no deeper than the number of
  97. + characters in the pattern. */
  98. {
  99. - unsigned int c; /* pattern char or start of range in [-] loop */
  100. + int c; /* pattern char or start of range in [-] loop */
  101. + /* Get first character, the pattern for new recmatch calls follows */
  102. + /* borrowed from Zip's global.c */
  103. + int no_wild = 0;
  104. + int allow_regex=1;
  105. + /* This fix provided by akt@m5.dion.ne.jp for Japanese.
  106. + See 21 July 2006 mail.
  107. + It only applies when p is pointing to a doublebyte character and
  108. + things like / and wildcards are not doublebyte. This probably
  109. + should not be needed. */
  110. - /* Get first character, the pattern for new recmatch calls follows */
  111. - c = *p; INCSTR(p);
  112. +#ifdef _MBCS
  113. + if (CLEN(p) == 2) {
  114. + if (CLEN(s) == 2) {
  115. + return (*p == *s && *(p+1) == *(s+1)) ?
  116. + recmatch(p + 2, s + 2, cs) : 0;
  117. + } else {
  118. + return 0;
  119. + }
  120. + }
  121. +#endif /* ?_MBCS */
  122. - /* If that was the end of the pattern, match if string empty too */
  123. - if (c == 0)
  124. - return *s == 0;
  125. + c = *POSTINCSTR(p);
  126. - /* '?' (or '%') matches any character (but not an empty string). */
  127. - if (c == WILDCHAR)
  128. -#ifdef WILD_STOP_AT_DIR
  129. - /* If uO.W_flag is non-zero, it won't match '/' */
  130. - return (*s && (!sepc || *s != (uch)sepc))
  131. - ? recmatch(p, s + CLEN(s), ic, sepc) : 0;
  132. -#else
  133. - return *s ? recmatch(p, s + CLEN(s), ic) : 0;
  134. -#endif
  135. + /* If that was the end of the pattern, match if string empty too */
  136. + if (c == 0)
  137. + return *s == 0;
  138. +
  139. + /* '?' (or '%' or '#') matches any character (but not an empty string) */
  140. + if (c == WILDCHR_SINGLE) {
  141. + if (wild_stop_at_dir)
  142. + return (*s && *s != DIRSEP_CHR) ? recmatch(p, s + CLEN(s), cs) : 0;
  143. + else
  144. + return *s ? recmatch(p, s + CLEN(s), cs) : 0;
  145. + }
  146. - /* '*' matches any number of characters, including zero */
  147. + /* WILDCHR_MULTI ('*') matches any number of characters, including zero */
  148. #ifdef AMIGA
  149. - if (c == '#' && *p == '?') /* "#?" is Amiga-ese for "*" */
  150. - c = '*', p++;
  151. + if (!no_wild && c == '#' && *p == '?') /* "#?" is Amiga-ese for "*" */
  152. + c = WILDCHR_MULTI, p++;
  153. #endif /* AMIGA */
  154. - if (c == '*') {
  155. -#ifdef WILD_STOP_AT_DIR
  156. - if (sepc) {
  157. - /* check for single "*" or double "**" */
  158. -# ifdef AMIGA
  159. - if ((c = p[0]) == '#' && p[1] == '?') /* "#?" is Amiga-ese for "*" */
  160. - c = '*', p++;
  161. - if (c != '*') {
  162. -# else /* !AMIGA */
  163. - if (*p != '*') {
  164. -# endif /* ?AMIGA */
  165. - /* single "*": this doesn't match the dirsep character */
  166. - for (; *s && *s != (uch)sepc; INCSTR(s))
  167. - if ((c = recmatch(p, s, ic, sepc)) != 0)
  168. - return (int)c;
  169. - /* end of pattern: matched if at end of string, else continue */
  170. - if (*p == '\0')
  171. - return (*s == 0);
  172. - /* continue to match if at sepc in pattern, else give up */
  173. - return (*p == (uch)sepc || (*p == '\\' && p[1] == (uch)sepc))
  174. - ? recmatch(p, s, ic, sepc) : 2;
  175. - }
  176. - /* "**": this matches slashes */
  177. - ++p; /* move p behind the second '*' */
  178. - /* and continue with the non-W_flag code variant */
  179. - }
  180. -#endif /* WILD_STOP_AT_DIR */
  181. + if (!no_wild && c == WILDCHR_MULTI)
  182. + {
  183. + if (wild_stop_at_dir) {
  184. + /* Check for an immediately following WILDCHR_MULTI */
  185. +# ifdef AMIGA
  186. + if ((c = p[0]) == '#' && p[1] == '?') /* "#?" is Amiga-ese for "*" */
  187. + c = WILDCHR_MULTI, p++;
  188. + if (c != WILDCHR_MULTI) {
  189. +# else /* !AMIGA */
  190. + if (*p != WILDCHR_MULTI) {
  191. +# endif /* ?AMIGA */
  192. + /* Single WILDCHR_MULTI ('*'): this doesn't match slashes */
  193. + for (; *s && *s != DIRSEP_CHR; INCSTR(s))
  194. + if ((c = recmatch(p, s, cs)) != 0)
  195. + return c;
  196. + /* end of pattern: matched if at end of string, else continue */
  197. if (*p == 0)
  198. - return 1;
  199. - if (isshexp((ZCONST char *)p) == NULL) {
  200. - /* Optimization for rest of pattern being a literal string:
  201. - * If there are no other shell expression chars in the rest
  202. - * of the pattern behind the multi-char wildcard, then just
  203. - * compare the literal string tail.
  204. - */
  205. - ZCONST uch *srest;
  206. -
  207. - srest = s + (strlen((ZCONST char *)s) - strlen((ZCONST char *)p));
  208. - if (srest - s < 0)
  209. - /* remaining literal string from pattern is longer than rest
  210. - * of test string, there can't be a match
  211. - */
  212. - return 0;
  213. - else
  214. - /* compare the remaining literal pattern string with the last
  215. - * bytes of the test string to check for a match
  216. - */
  217. + return (*s == 0);
  218. + /* continue to match if at DIRSEP_CHR in pattern, else give up */
  219. + return (*p == DIRSEP_CHR || (*p == '\\' && p[1] == DIRSEP_CHR))
  220. + ? recmatch(p, s, cs) : 2;
  221. + }
  222. + /* Two consecutive WILDCHR_MULTI ("**"): this matches DIRSEP_CHR ('/') */
  223. + p++; /* move p past the second WILDCHR_MULTI */
  224. + /* continue with the normal non-WILD_STOP_AT_DIR code */
  225. + } /* wild_stop_at_dir */
  226. +
  227. + /* Not wild_stop_at_dir */
  228. + if (*p == 0)
  229. + return 1;
  230. + if (!isshexp((char *)p))
  231. + {
  232. + /* optimization for rest of pattern being a literal string */
  233. +
  234. + /* optimization to handle patterns like *.txt */
  235. + /* if the first char in the pattern is '*' and there */
  236. + /* are no other shell expression chars, i.e. a literal string */
  237. + /* then just compare the literal string at the end */
  238. +
  239. + ZCONST char *srest;
  240. +
  241. + srest = s + (strlen(s) - strlen(p));
  242. + if (srest - s < 0)
  243. + /* remaining literal string from pattern is longer than rest of
  244. + test string, there can't be a match
  245. + */
  246. + return 0;
  247. + else
  248. + /* compare the remaining literal pattern string with the last bytes
  249. + of the test string to check for a match */
  250. #ifdef _MBCS
  251. - {
  252. - ZCONST uch *q = s;
  253. + {
  254. + ZCONST char *q = s;
  255. - /* MBCS-aware code must not scan backwards into a string from
  256. - * the end.
  257. - * So, we have to move forward by character from our well-known
  258. - * character position s in the test string until we have
  259. - * advanced to the srest position.
  260. - */
  261. - while (q < srest)
  262. - INCSTR(q);
  263. - /* In case the byte *srest is a trailing byte of a multibyte
  264. - * character in the test string s, we have actually advanced
  265. - * past the position (srest).
  266. - * For this case, the match has failed!
  267. - */
  268. - if (q != srest)
  269. - return 0;
  270. - return ((ic
  271. - ? namecmp((ZCONST char *)p, (ZCONST char *)q)
  272. - : strcmp((ZCONST char *)p, (ZCONST char *)q)
  273. - ) == 0);
  274. - }
  275. + /* MBCS-aware code must not scan backwards into a string from
  276. + * the end.
  277. + * So, we have to move forward by character from our well-known
  278. + * character position s in the test string until we have advanced
  279. + * to the srest position.
  280. + */
  281. + while (q < srest)
  282. + INCSTR(q);
  283. + /* In case the byte *srest is a trailing byte of a multibyte
  284. + * character, we have actually advanced past the position (srest).
  285. + * For this case, the match has failed!
  286. + */
  287. + if (q != srest)
  288. + return 0;
  289. + return ((cs ? strcmp(p, q) : namecmp(p, q)) == 0);
  290. + }
  291. #else /* !_MBCS */
  292. - return ((ic
  293. - ? namecmp((ZCONST char *)p, (ZCONST char *)srest)
  294. - : strcmp((ZCONST char *)p, (ZCONST char *)srest)
  295. - ) == 0);
  296. + return ((cs ? strcmp(p, srest) : namecmp(p, srest)) == 0);
  297. #endif /* ?_MBCS */
  298. - } else {
  299. - /* pattern contains more wildcards, continue with recursion... */
  300. - for (; *s; INCSTR(s))
  301. - if ((c = recmatch(p, s, ic __WDL)) != 0)
  302. - return (int)c;
  303. - return 2; /* 2 means give up--match will return false */
  304. - }
  305. }
  306. -
  307. - /* Parse and process the list of characters and ranges in brackets */
  308. - if (c == BEG_RANGE) {
  309. - int e; /* flag true if next char to be taken literally */
  310. - ZCONST uch *q; /* pointer to end of [-] group */
  311. - int r; /* flag true to match anything but the range */
  312. -
  313. - if (*s == 0) /* need a character to match */
  314. - return 0;
  315. - p += (r = (*p == '!' || *p == '^')); /* see if reverse */
  316. - for (q = p, e = 0; *q; INCSTR(q)) /* find closing bracket */
  317. - if (e)
  318. - e = 0;
  319. - else
  320. - if (*q == '\\') /* GRR: change to ^ for MS-DOS, OS/2? */
  321. - e = 1;
  322. - else if (*q == END_RANGE)
  323. - break;
  324. - if (*q != END_RANGE) /* nothing matches if bad syntax */
  325. - return 0;
  326. - for (c = 0, e = (*p == '-'); p < q; INCSTR(p)) {
  327. - /* go through the list */
  328. - if (!e && *p == '\\') /* set escape flag if \ */
  329. - e = 1;
  330. - else if (!e && *p == '-') /* set start of range if - */
  331. - c = *(p-1);
  332. - else {
  333. - unsigned int cc = Case(*s);
  334. -
  335. - if (*(p+1) != '-')
  336. - for (c = c ? c : *p; c <= *p; c++) /* compare range */
  337. - if ((unsigned)Case(c) == cc) /* typecast for MSC bug */
  338. - return r ? 0 : recmatch(q + 1, s + 1, ic __WDL);
  339. - c = e = 0; /* clear range, escape flags */
  340. - }
  341. - }
  342. - return r ? recmatch(q + CLEN(q), s + CLEN(s), ic __WDL) : 0;
  343. - /* bracket match failed */
  344. + else
  345. + {
  346. + /* pattern contains more wildcards, continue with recursion... */
  347. + for (; *s; INCSTR(s))
  348. + if ((c = recmatch(p, s, cs)) != 0)
  349. + return c;
  350. + return 2; /* 2 means give up--shmatch will return false */
  351. }
  352. + }
  353. - /* if escape ('\\'), just compare next character */
  354. - if (c == '\\' && (c = *p++) == 0) /* if \ at end, then syntax error */
  355. - return 0;
  356. +#ifndef VMS /* No bracket matching in VMS */
  357. + /* Parse and process the list of characters and ranges in brackets */
  358. + if (!no_wild && allow_regex && c == '[')
  359. + {
  360. + int e; /* flag true if next char to be taken literally */
  361. + ZCONST char *q; /* pointer to end of [-] group */
  362. + int r; /* flag true to match anything but the range */
  363. +
  364. + if (*s == 0) /* need a character to match */
  365. + return 0;
  366. + p += (r = (*p == '!' || *p == '^')); /* see if reverse */
  367. + for (q = p, e = 0; *q; q++) /* find closing bracket */
  368. + if (e)
  369. + e = 0;
  370. + else
  371. + if (*q == '\\')
  372. + e = 1;
  373. + else if (*q == ']')
  374. + break;
  375. + if (*q != ']') /* nothing matches if bad syntax */
  376. + return 0;
  377. + for (c = 0, e = *p == '-'; p < q; p++) /* go through the list */
  378. + {
  379. + if (e == 0 && *p == '\\') /* set escape flag if \ */
  380. + e = 1;
  381. + else if (e == 0 && *p == '-') /* set start of range if - */
  382. + c = *(p-1);
  383. + else
  384. + {
  385. + uch cc = (cs ? (uch)*s : case_map((uch)*s));
  386. + uch uc = (uch) c;
  387. + if (*(p+1) != '-')
  388. + for (uc = uc ? uc : (uch)*p; uc <= (uch)*p; uc++)
  389. + /* compare range */
  390. + if ((cs ? uc : case_map(uc)) == cc)
  391. + return r ? 0 : recmatch(q + CLEN(q), s + CLEN(s), cs);
  392. + c = e = 0; /* clear range, escape flags */
  393. + }
  394. + }
  395. + return r ? recmatch(q + CLEN(q), s + CLEN(s), cs) : 0;
  396. + /* bracket match failed */
  397. + }
  398. +#endif /* !VMS */
  399. - /* just a character--compare it */
  400. -#ifdef QDOS
  401. - return QMatch(Case((uch)c), Case(*s)) ?
  402. - recmatch(p, s + CLEN(s), ic __WDL) : 0;
  403. -#else
  404. - return Case((uch)c) == Case(*s) ?
  405. - recmatch(p, s + CLEN(s), ic __WDL) : 0;
  406. -#endif
  407. + /* If escape ('\'), just compare next character */
  408. + if (!no_wild && c == '\\')
  409. + if ((c = *p++) == '\0') /* if \ at end, then syntax error */
  410. + return 0;
  411. +
  412. +#ifdef VMS
  413. + /* 2005-11-06 SMS.
  414. + Handle "..." wildcard in p with "." or "]" in s.
  415. + */
  416. + if ((c == '.') && (*p == '.') && (*(p+ CLEN( p)) == '.') &&
  417. + ((*s == '.') || (*s == ']')))
  418. + {
  419. + /* Match "...]" with "]". Continue after "]" in both. */
  420. + if ((*(p+ 2* CLEN( p)) == ']') && (*s == ']'))
  421. + return recmatch( (p+ 3* CLEN( p)), (s+ CLEN( s)), cs);
  422. +
  423. + /* Else, look for a reduced match in s, until "]" in or end of s. */
  424. + for (; *s && (*s != ']'); INCSTR(s))
  425. + if (*s == '.')
  426. + /* If reduced match, then continue after "..." in p, "." in s. */
  427. + if ((c = recmatch( (p+ CLEN( p)), s, cs)) != 0)
  428. + return (int)c;
  429. +
  430. + /* Match "...]" with "]". Continue after "]" in both. */
  431. + if ((*(p+ 2* CLEN( p)) == ']') && (*s == ']'))
  432. + return recmatch( (p+ 3* CLEN( p)), (s+ CLEN( s)), cs);
  433. +
  434. + /* No reduced match. Quit. */
  435. + return 2;
  436. + }
  437. +
  438. +#endif /* def VMS */
  439. +
  440. + /* Just a character--compare it */
  441. + return (cs ? c == *s : case_map((uch)c) == case_map((uch)*s)) ?
  442. + recmatch(p, s + CLEN(s), cs) : 0;
  443. +}
  444. -} /* end function recmatch() */
  445. +/*************************************************************************************************/
  446. static char *isshexp(p)
  447. ZCONST char *p;
  448. /* If p is a sh expression, a pointer to the first special character is