PageRenderTime 41ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/Src/Modules/regex.c

https://bitbucket.org/ZyX_I/zsh
C | 250 lines | 178 code | 23 blank | 49 comment | 21 complexity | 7c878ca9452e6a108566469e2386163e MD5 | raw file
  1. /*
  2. * regex.c
  3. *
  4. * This file is part of zsh, the Z shell.
  5. *
  6. * Copyright (c) 2007,2012 Phil Pennock
  7. * All Rights Reserved.
  8. *
  9. * Permission is hereby granted, without written agreement and without
  10. * license or royalty fees, to use, copy, modify, and distribute this
  11. * software and to distribute modified versions of this software for any
  12. * purpose, provided that the above copyright notice and the following
  13. * two paragraphs appear in all copies of this software.
  14. *
  15. * In no event shall Phil Pennock or the Zsh Development Group be liable
  16. * to any party for direct, indirect, special, incidental, or consequential
  17. * damages arising out of the use of this software and its documentation,
  18. * even if Phil Pennock and the Zsh Development Group have been advised of
  19. * the possibility of such damage.
  20. *
  21. * Phil Pennock and the Zsh Development Group specifically disclaim any
  22. * warranties, including, but not limited to, the implied warranties of
  23. * merchantability and fitness for a particular purpose. The software
  24. * provided hereunder is on an "as is" basis, and Phil Pennock and the
  25. * Zsh Development Group have no obligation to provide maintenance,
  26. * support, updates, enhancements, or modifications.
  27. *
  28. */
  29. #include "regex.mdh"
  30. #include "regex.pro"
  31. #include <regex.h>
  32. /* we default to a vaguely modern syntax and set of capabilities */
  33. #define ZREGEX_EXTENDED 0
  34. /* if you want Basic syntax, make it an alternative options */
  35. static void
  36. zregex_regerrwarn(int r, regex_t *re, char *msg)
  37. {
  38. char *errbuf;
  39. size_t errbufsz;
  40. errbufsz = regerror(r, re, NULL, 0);
  41. errbuf = zalloc(errbufsz*sizeof(char));
  42. regerror(r, re, errbuf, errbufsz);
  43. zwarn("%s: %s", msg, errbuf);
  44. zfree(errbuf, errbufsz);
  45. }
  46. /**/
  47. static int
  48. zcond_regex_match(char **a, int id)
  49. {
  50. regex_t re;
  51. regmatch_t *m, *matches = NULL;
  52. size_t matchessz = 0;
  53. char *lhstr, *lhstr_zshmeta, *rhre, *rhre_zshmeta, *s, **arr, **x;
  54. int r, n, return_value, rcflags, reflags, nelem, start;
  55. lhstr_zshmeta = cond_str(a,0,0);
  56. rhre_zshmeta = cond_str(a,1,0);
  57. rcflags = reflags = 0;
  58. return_value = 0; /* 1 => matched successfully */
  59. lhstr = ztrdup(lhstr_zshmeta);
  60. unmetafy(lhstr, NULL);
  61. rhre = ztrdup(rhre_zshmeta);
  62. unmetafy(rhre, NULL);
  63. switch(id) {
  64. case ZREGEX_EXTENDED:
  65. rcflags |= REG_EXTENDED;
  66. if (!isset(CASEMATCH))
  67. rcflags |= REG_ICASE;
  68. r = regcomp(&re, rhre, rcflags);
  69. if (r) {
  70. zregex_regerrwarn(r, &re, "failed to compile regex");
  71. break;
  72. }
  73. /* re.re_nsub is number of parenthesized groups, we also need
  74. * 1 for the 0 offset, which is the entire matched portion
  75. */
  76. if ((int)re.re_nsub < 0) {
  77. zwarn("INTERNAL ERROR: regcomp() returned "
  78. "negative subpattern count %d", (int)re.re_nsub);
  79. break;
  80. }
  81. matchessz = (re.re_nsub + 1) * sizeof(regmatch_t);
  82. matches = zalloc(matchessz);
  83. r = regexec(&re, lhstr, re.re_nsub+1, matches, reflags);
  84. if (r == REG_NOMATCH)
  85. ; /* We do nothing when we fail to match. */
  86. else if (r == 0) {
  87. return_value = 1;
  88. if (isset(BASHREMATCH)) {
  89. start = 0;
  90. nelem = re.re_nsub + 1;
  91. } else {
  92. start = 1;
  93. nelem = re.re_nsub;
  94. }
  95. arr = NULL; /* bogus gcc warning of used uninitialised */
  96. /* entire matched portion + re_nsub substrings + NULL */
  97. if (nelem) {
  98. arr = x = (char **) zalloc(sizeof(char *) * (nelem + 1));
  99. for (m = matches + start, n = start; n <= (int)re.re_nsub; ++n, ++m, ++x) {
  100. *x = metafy(lhstr + m->rm_so, m->rm_eo - m->rm_so, META_DUP);
  101. }
  102. *x = NULL;
  103. }
  104. if (isset(BASHREMATCH)) {
  105. setaparam("BASH_REMATCH", arr);
  106. } else {
  107. zlong offs;
  108. char *ptr;
  109. m = matches;
  110. s = metafy(lhstr + m->rm_so, m->rm_eo - m->rm_so, META_DUP);
  111. setsparam("MATCH", s);
  112. /*
  113. * Count the characters before the match.
  114. */
  115. ptr = lhstr;
  116. offs = 0;
  117. MB_METACHARINIT();
  118. while (ptr < lhstr + m->rm_so) {
  119. offs++;
  120. ptr += MB_METACHARLEN(ptr);
  121. }
  122. setiparam("MBEGIN", offs + !isset(KSHARRAYS));
  123. /*
  124. * Add on the characters in the match.
  125. */
  126. while (ptr < lhstr + m->rm_eo) {
  127. offs++;
  128. ptr += MB_METACHARLEN(ptr);
  129. }
  130. setiparam("MEND", offs + !isset(KSHARRAYS) - 1);
  131. if (nelem) {
  132. char **mbegin, **mend, **bptr, **eptr;
  133. bptr = mbegin = (char **)zalloc(sizeof(char *)*(nelem+1));
  134. eptr = mend = (char **)zalloc(sizeof(char *)*(nelem+1));
  135. for (m = matches + start, n = 0;
  136. n < nelem;
  137. ++n, ++m, ++bptr, ++eptr)
  138. {
  139. char buf[DIGBUFSIZE];
  140. ptr = lhstr;
  141. offs = 0;
  142. /* Find the start offset */
  143. MB_METACHARINIT();
  144. while (ptr < lhstr + m->rm_so) {
  145. offs++;
  146. ptr += MB_METACHARLEN(ptr);
  147. }
  148. convbase(buf, offs + !isset(KSHARRAYS), 10);
  149. *bptr = ztrdup(buf);
  150. /* Continue to the end offset */
  151. while (ptr < lhstr + m->rm_eo) {
  152. offs++;
  153. ptr += MB_METACHARLEN(ptr);
  154. }
  155. convbase(buf, offs + !isset(KSHARRAYS) - 1, 10);
  156. *eptr = ztrdup(buf);
  157. }
  158. *bptr = *eptr = NULL;
  159. setaparam("match", arr);
  160. setaparam("mbegin", mbegin);
  161. setaparam("mend", mend);
  162. }
  163. }
  164. }
  165. else
  166. zregex_regerrwarn(r, &re, "regex matching error");
  167. break;
  168. default:
  169. DPUTS(1, "bad regex option");
  170. return_value = 0;
  171. goto CLEAN_BASEMETA;
  172. }
  173. if (matches)
  174. zfree(matches, matchessz);
  175. regfree(&re);
  176. CLEAN_BASEMETA:
  177. free(lhstr);
  178. free(rhre);
  179. return return_value;
  180. }
  181. static struct conddef cotab[] = {
  182. CONDDEF("regex-match", CONDF_INFIX, zcond_regex_match, 0, 0, ZREGEX_EXTENDED)
  183. };
  184. static struct features module_features = {
  185. NULL, 0,
  186. cotab, sizeof(cotab)/sizeof(*cotab),
  187. NULL, 0,
  188. NULL, 0,
  189. 0
  190. };
  191. /**/
  192. int
  193. setup_(UNUSED(Module m))
  194. {
  195. return 0;
  196. }
  197. /**/
  198. int
  199. features_(Module m, char ***features)
  200. {
  201. *features = featuresarray(m, &module_features);
  202. return 0;
  203. }
  204. /**/
  205. int
  206. enables_(Module m, int **enables)
  207. {
  208. return handlefeatures(m, &module_features, enables);
  209. }
  210. /**/
  211. int
  212. boot_(Module m)
  213. {
  214. return 0;
  215. }
  216. /**/
  217. int
  218. cleanup_(Module m)
  219. {
  220. return setfeatureenables(m, &module_features, NULL);
  221. }
  222. /**/
  223. int
  224. finish_(UNUSED(Module m))
  225. {
  226. return 0;
  227. }