PageRenderTime 49ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/quakeforge/branches/release_0_5_3/libs/gib/gib_regex.c

#
C | 194 lines | 140 code | 19 blank | 35 comment | 27 complexity | e3d1178ab54f4a4a1a4a9bd44e6ff99b MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, AGPL-3.0, AGPL-1.0, Unlicense
  1. /*
  2. #FILENAME#
  3. #DESCRIPTION#
  4. Copyright (C) 2002 #AUTHOR#
  5. Author: #AUTHOR#
  6. Date: #DATE#
  7. This program is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU General Public License
  9. as published by the Free Software Foundation; either version 2
  10. of the License, or (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. See the GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to:
  17. Free Software Foundation, Inc.
  18. 59 Temple Place - Suite 330
  19. Boston, MA 02111-1307, USA
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. # include "config.h"
  23. #endif
  24. static __attribute__ ((unused))
  25. const char rcsid[] =
  26. "$Id: gib_regex.c 9722 2003-07-15 21:40:37Z snax $";
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <ctype.h>
  30. #include <sys/types.h>
  31. #include "regex.h"
  32. #include "QF/dstring.h"
  33. #include "QF/hash.h"
  34. #include "gib_regex.h"
  35. #include "QF/qtypes.h"
  36. hashtab_t *gib_regexs;
  37. static char errstr[1024];
  38. static const char *
  39. GIB_Regex_Get_Key (void *ele, void *ptr)
  40. {
  41. return ((gib_regex_t *) ele)->regex;
  42. }
  43. static void
  44. GIB_Regex_Free (void *ele, void *ptr)
  45. {
  46. regfree (&(((gib_regex_t *) ele)->comp));
  47. free (((gib_regex_t *) ele)->regex);
  48. free (ele);
  49. }
  50. void
  51. GIB_Regex_Init (void)
  52. {
  53. gib_regexs = Hash_NewTable (512, GIB_Regex_Get_Key, GIB_Regex_Free, 0);
  54. }
  55. regex_t *
  56. GIB_Regex_Compile (const char *regex, int cflags)
  57. {
  58. static unsigned int num_regexs = 0;
  59. gib_regex_t *reg;
  60. int res;
  61. // Already compiled ?
  62. if ((reg = Hash_Find (gib_regexs, regex))) {
  63. // Did cflags change?
  64. if (cflags != reg->cflags) {
  65. // Try to recompile
  66. reg->cflags = cflags;
  67. if ((res = regcomp (&(reg->comp), regex, cflags))) {
  68. // Blew up, remove from hash
  69. regerror (res, &(reg->comp), errstr, sizeof (errstr));
  70. regfree (&(reg->comp));
  71. free (reg->regex);
  72. free (Hash_Del (gib_regexs, regex));
  73. num_regexs--;
  74. return 0;
  75. } else
  76. return &(reg->comp);
  77. } else
  78. return &(reg->comp);
  79. } else {
  80. reg = calloc (1, sizeof (gib_regex_t));
  81. if ((res = regcomp (&(reg->comp), regex, cflags))) {
  82. regerror (res, &(reg->comp), errstr, sizeof (errstr));
  83. regfree (&(reg->comp));
  84. free (reg);
  85. return 0;
  86. } else {
  87. reg->cflags = cflags;
  88. reg->regex = strdup (regex);
  89. if (++num_regexs > 128) {
  90. Hash_FlushTable (gib_regexs);
  91. num_regexs = 0;
  92. }
  93. Hash_Add (gib_regexs, reg);
  94. return &(reg->comp);
  95. }
  96. }
  97. }
  98. const char *
  99. GIB_Regex_Error (void)
  100. {
  101. return errstr;
  102. }
  103. int
  104. GIB_Regex_Translate_Options (const char *opstr)
  105. {
  106. int options = 0;
  107. if (strchr (opstr, 'i'))
  108. options |= REG_ICASE;
  109. if (strchr (opstr, 'n'))
  110. options |= REG_NEWLINE;
  111. return options;
  112. }
  113. int
  114. GIB_Regex_Translate_Runtime_Options (const char *opstr)
  115. {
  116. int options = 0;
  117. if (strchr (opstr, '<'))
  118. options |= REG_NOTBOL;
  119. if (strchr (opstr, '>'))
  120. options |= REG_NOTEOL;
  121. return options;
  122. }
  123. unsigned int
  124. GIB_Regex_Apply_Match (regmatch_t match[10], dstring_t * dstr, unsigned int ofs,
  125. const char *replace)
  126. {
  127. int i, start, len, sub, rlen = strlen (replace);
  128. char *matched;
  129. start = match[0].rm_so + ofs;
  130. len = match[0].rm_eo - match[0].rm_so;
  131. // Save matched pattern space
  132. matched = calloc (len + 1, sizeof (char));
  133. memcpy (matched, dstr->str + start, match[0].rm_eo - match[0].rm_so);
  134. dstring_replace (dstr, start, len, replace, rlen);
  135. for (i = start; i < start + rlen; i++) {
  136. if (dstr->str[i] == '\\') {
  137. if (dstr->str[i + 1] == '&') {
  138. dstring_snip (dstr, i, 1);
  139. rlen--;
  140. continue;
  141. }
  142. if (isdigit ((byte) dstr->str[i + 1])) {
  143. if (i && dstr->str[i - 1] == '\\') { // Escaped, not a true
  144. // back reference
  145. dstring_snip (dstr, i, 1);
  146. rlen--;
  147. continue;
  148. }
  149. sub = dstr->str[i + 1] - '0';
  150. if (match[sub].rm_so != -1) {
  151. dstring_replace (dstr, i, 2, matched + match[sub].rm_so,
  152. match[sub].rm_eo - match[sub].rm_so);
  153. rlen += match[sub].rm_eo - match[sub].rm_so - 2;
  154. } else {
  155. dstring_snip (dstr, i, 2);
  156. rlen -= 2;
  157. }
  158. }
  159. } else if (dstr->str[i] == '&') {
  160. dstring_replace (dstr, i, 1, matched, len);
  161. rlen += strlen (matched) - 1;
  162. }
  163. }
  164. free (matched);
  165. return rlen + match[0].rm_so;
  166. }