1 /*
2 * Copyright (c) 2000-2003, Darren Hiebert
3 *
4 * This source code is released for free distribution under the terms of the
5 * GNU General Public License version 2 or (at your option) any later version.
6 *
7 * This module contains functions for applying regular expression matching.
8 *
9 * The code for utilizing the Gnu regex package with regards to processing the
10 * regex option and checking for regex matches was adapted from routines in
11 * Gnu etags.
12 */
13
14 /*
15 * INCLUDE FILES
16 */
17 #include "general.h" /* must always come first */
18
19 #include <regex.h>
20 #include "lregex_p.h"
21
22 /*
23 * FUNCTION DECLARATIONS
24 */
25 static int match (struct regexBackend *backend,
26 void *code, const char *input, size_t size,
27 regmatch_t pmatch[BACK_REFERENCE_COUNT]);
28 static regexCompiledCode compile (struct regexBackend *backend,
29 const char *const regexp,
30 int flags);
31 static void delete_code (void *code);
32 static void set_icase_flag (int *flags);
33
34 /*
35 * DATA DEFINITIONS
36 */
37 static struct regexBackend defaultRegexBackend = {
38 .fdefs = NULL,
39 .fdef_count = 0,
40 .set_icase_flag = set_icase_flag,
41 .compile = compile,
42 .match = match,
43 .delete_code = delete_code,
44 };
45
46 /*
47 * FUNCTOIN DEFINITIONS
48 */
basic_regex_flag_short(char c,void * data)49 extern void basic_regex_flag_short (char c, void* data)
50 {
51 struct flagDefsDescriptor *desc = data;
52
53 if (desc->backend)
54 error (FATAL, "regex backed is specified twice: %c", c);
55
56 desc->backend = &defaultRegexBackend;
57 desc->flags = (desc->regptype == REG_PARSER_MULTI_TABLE)? 0: REG_NEWLINE;
58 }
59
basic_regex_flag_long(const char * const s,const char * const unused CTAGS_ATTR_UNUSED,void * data)60 extern void basic_regex_flag_long (const char* const s, const char* const unused CTAGS_ATTR_UNUSED, void* data)
61 {
62 struct flagDefsDescriptor *desc = data;
63
64 if (desc->backend)
65 error (FATAL, "regex backed is specified twice: %s", s);
66
67 basic_regex_flag_short ('b', data);
68 }
69
extend_regex_flag_short(char c,void * data)70 extern void extend_regex_flag_short (char c, void* data)
71 {
72 struct flagDefsDescriptor *desc = data;
73
74 if (desc->backend)
75 error (FATAL, "regex backed is specified twice: %c", c);
76
77 desc->backend = &defaultRegexBackend;
78 desc->flags = REG_EXTENDED;
79 desc->flags |= (desc->regptype == REG_PARSER_MULTI_TABLE)? 0: REG_NEWLINE;
80 }
81
extend_regex_flag_long(const char * const s,const char * const unused CTAGS_ATTR_UNUSED,void * data)82 extern void extend_regex_flag_long (const char* const s, const char* const unused CTAGS_ATTR_UNUSED, void* data)
83 {
84 struct flagDefsDescriptor *desc = data;
85
86 if (desc->backend)
87 error (FATAL, "regex backed is specified twice: %s", s);
88
89 extend_regex_flag_short('e', data);
90 }
91
delete_code(void * code)92 static void delete_code (void *code)
93 {
94 regex_t *regex_code = code;
95 regfree (regex_code);
96 eFree (regex_code);
97 }
98
compile(struct regexBackend * backend,const char * const regexp,int flags)99 static regexCompiledCode compile (struct regexBackend *backend,
100 const char *const regexp,
101 int flags)
102 {
103 regex_t *regex_code = xMalloc (1, regex_t);
104 int errcode = regcomp (regex_code, regexp, flags);
105 if (errcode != 0)
106 {
107 char errmsg[256];
108 regerror (errcode, regex_code, errmsg, 256);
109 error (WARNING, "regcomp: %s", errmsg);
110 regfree (regex_code);
111 eFree (regex_code);
112 return (regexCompiledCode) { .backend = NULL, .code = NULL };
113 }
114 return (regexCompiledCode) { .backend = &defaultRegexBackend, .code = regex_code };
115 }
116
match(struct regexBackend * backend,void * code,const char * input,size_t size CTAGS_ATTR_UNUSED,regmatch_t pmatch[BACK_REFERENCE_COUNT])117 static int match (struct regexBackend *backend,
118 void *code, const char *input, size_t size CTAGS_ATTR_UNUSED,
119 regmatch_t pmatch[BACK_REFERENCE_COUNT])
120 {
121 return regexec ((regex_t *)code, input, BACK_REFERENCE_COUNT, pmatch, 0);
122 }
123
set_icase_flag(int * flags)124 static void set_icase_flag (int *flags)
125 {
126 *flags |= REG_ICASE;
127 }
128