xref: /Universal-ctags/main/lregex-default.c (revision c30b89ac766f5d1fb09918f3f16b0f01d57e0324)
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