1 /* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
2 * Understanding is not required. Only obedience.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 3 of the License ONLY.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 typedef struct recache_item_s
{
22 regexp_t re
; /* this MUST be here! */
23 struct recache_item_s
*next
; /* for 'same string, different flags' */
27 static struct hash
*recache
= NULL
;
30 /* return 0 if not found (created new ci) */
31 static int find_re (regexp_t
**ci
, const char *str
, int flags
) {
33 recache_item_t fnd
, *res
= &fnd
;
34 if (recache
== NULL
) recache
= hashinit(sizeof(recache_item_t
), "recache");
35 fnd
.re
.restr
= newstr(str
);
36 if (hashenter(recache
, (HASHDATA
**)&res
)) {
38 res
->re
.flags
= flags
;
42 //fprintf(stderr, "NEW RE: '%s'\n", str);
44 /* hit; check if we have regexp with this set of flags */
46 for (c
= res
; c
!= NULL
; c
= c
->next
) if (c
->re
.flags
== flags
) break;
48 /* not found; create new item */
50 for (last
= res
; last
->next
!= NULL
; last
= last
->next
) ;
51 if ((c
= malloc(sizeof(*c
))) == NULL
) { printf("FATAL: out of memory!\n"); exit(EXITBAD
); }
52 c
->re
.restr
= res
->re
.restr
;
53 c
->re
.flags
= res
->re
.flags
;
59 //fprintf(stderr, "NEW RE(1): '%s'\n", str);
62 //fprintf(stderr, "RE HIT: '%s'\n", str);
73 * u: this is utf-8 string
74 * m: '.' matches newline
75 * default mode: non-utf-8 (it can be only reset with /.../u)
77 regexp_t
*regexp_compile (const char *str
, int flags
) {
79 const char *s
= str
, *e
= NULL
, *errmsg
;
80 flags
|= RE9_FLAG_NONUTF8
;
81 if (str
== NULL
) str
= "";
82 if (str
[0] == '/' && (e
= strrchr(str
+1, '/')) != NULL
) {
83 /* this must be regexp with options */
84 for (const char *t
= e
+1; *t
; ++t
) {
86 case 'i': flags
|= RE9_FLAG_CASEINSENS
; break;
87 case 'u': flags
&= ~RE9_FLAG_NONUTF8
; break;
88 case 'm': flags
|= RE9_FLAG_ANYDOT
; break;
90 printf("FATAL: invalid regexp option: '%c'!\n", *t
);
91 exit(EXITBAD
); /* oops */
96 if (find_re(&cre
, s
, flags
) == 0) {
97 if ((cre
->re
= re9_compile_ex(str
, e
, flags
, &errmsg
)) == NULL
) {
98 printf("FATAL: regexp error: '%s'!\n", errmsg
);
99 exit(EXITBAD
); /* oops */
101 flags
&= ~RE9_FLAG_ANYDOT
; /* don't need that */
102 /* RE9_FLAG_CASEINSENS left only for caller checks; re9_execute() will ignore it */
109 void regexp_free (regexp_t
*re
) {
110 /* do nothing, yeah! */
114 int regexp_execute (regexp_t
*re
, const char *bol
, re9_sub_t
*mp
, int ms
) {
116 #ifdef REGEXP9_DEBUG_MEMSIZE
117 int res
= re9_execute(re
->re
, re
->flags
, bol
, mp
, ms
);
118 if (re9_memused
> re
->maxmem
) re
->maxmem
= re9_memused
;
121 return re9_execute(re
->re
, re
->flags
, bol
, mp
, ms
);
128 void regexp_done (void) {
129 #ifdef REGEXP9_DEBUG_MEMSIZE
132 hashiterate(recache
, ({ int lmb (const void *hdata
, void *udata
) { ++count
; return 0; } lmb
; }), NULL
);
133 rarray
= malloc(sizeof(rarray
[0])*count
);
135 hashiterate(recache
, ({ int lmb (const void *hdata
, void *udata
) { rarray
[count
++] = *((regexp_t
*)hdata
); return 0; } lmb
; }), NULL
);
136 printf("regexps, sorted by used memory:\n");
137 qsort(rarray
, count
, sizeof(rarray
[0]), ({
138 int cmp (const void *p0
, const void *p1
) {
139 regexp_t
*r0
= (regexp_t
*)p0
;
140 regexp_t
*r1
= (regexp_t
*)p1
;
141 if (r0
->maxmem
!= r1
->maxmem
) return r1
->maxmem
-r0
->maxmem
;
142 if (strlen(r0
->restr
) != strlen(r1
->restr
)) return strlen(r0
->restr
)-strlen(r1
->restr
);
143 return strcmp(r0
->restr
, r1
->restr
);
147 for (int f
= 0; f
< count
; ++f
) printf("%10d: /%s/\n", rarray
[f
].maxmem
, rarray
[f
].restr
);