gmatch.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * Derived from /usr/src/cmd/sh/expand.c, Unix 7th Edition:
  3. *
  4. * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * Redistributions of source code and documentation must retain the
  10. * above copyright notice, this list of conditions and the following
  11. * disclaimer.
  12. * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * All advertising materials mentioning features or use of this software
  16. * must display the following acknowledgement:
  17. * This product includes software developed or owned by Caldera
  18. * International, Inc.
  19. * Neither the name of Caldera International, Inc. nor the names of
  20. * other contributors may be used to endorse or promote products
  21. * derived from this software without specific prior written permission.
  22. *
  23. * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
  24. * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
  25. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  26. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27. * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
  28. * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
  29. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  30. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  31. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  32. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  33. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  34. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  35. */
  36. #if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4
  37. #define USED __attribute__ ((used))
  38. #elif defined __GNUC__
  39. #define USED __attribute__ ((unused))
  40. #else
  41. #define USED
  42. #endif
  43. static const char sccsid[] USED = "@(#)gmatch.sl 1.5 (gritter) 5/29/05";
  44. #include <stdlib.h>
  45. #include <wchar.h>
  46. #include <limits.h>
  47. #include "mbtowi.h"
  48. #define fetch(wc, s, n) ((mb_cur_max > 1 && *(s) & 0200 ? \
  49. ((n) = mbtowi(&(wc), (s), mb_cur_max), \
  50. (n) = ((n) > 0 ? (n) : (n) < 0 ? (wc = WEOF, 1) : 1)) :\
  51. ((wc) = *(s) & 0377, (n) = 1)), (s) += (n), (wc))
  52. int
  53. gmatch(const char *s, const char *p)
  54. {
  55. const char *bs = s;
  56. int mb_cur_max = MB_CUR_MAX;
  57. wint_t c, scc;
  58. int n;
  59. if (fetch(scc, s, n) == WEOF)
  60. return (0);
  61. switch (fetch(c, p, n)) {
  62. case '[': {
  63. int ok = 0, excl;
  64. unsigned long lc = ULONG_MAX;
  65. const char *bp;
  66. if (*p == '!') {
  67. p++;
  68. excl = 1;
  69. } else
  70. excl = 0;
  71. fetch(c, p, n);
  72. bp = p;
  73. while (c != '\0') {
  74. if (c == ']' && p > bp)
  75. return (ok ^ excl ? gmatch(s, p) : 0);
  76. else if (c == '-' && p > bp && *p != ']') {
  77. if (*p == '\\')
  78. p++;
  79. if (fetch(c, p, n) == '\0')
  80. break;
  81. if (lc <= scc && scc <= c)
  82. ok = 1;
  83. } else {
  84. if (c == '\\') {
  85. if (fetch(c, p, n) == '\0')
  86. break;
  87. }
  88. if (scc == (lc = c))
  89. ok = 1;
  90. }
  91. fetch(c, p, n);
  92. }
  93. return (0);
  94. }
  95. case '\\':
  96. fetch(c, p, n);
  97. if (c == '\0')
  98. return (0);
  99. /*FALLTHRU*/
  100. default:
  101. if (c != scc)
  102. return (0);
  103. /*FALLTHRU*/
  104. case '?':
  105. return (scc ? gmatch(s, p) : 0);
  106. case '*':
  107. if (*p == '\0')
  108. return (1);
  109. s = bs;
  110. while (*s) {
  111. if (gmatch(s, p))
  112. return (1);
  113. fetch(scc, s, n);
  114. }
  115. return (0);
  116. case '\0':
  117. return (scc == '\0');
  118. case WEOF:
  119. return (0);
  120. }
  121. }