Line | Count | Source |
1 | | /** regex - regular expression functions related to POSIX regex lib. */ |
2 | | |
3 | | /* SPDX-License-Identifier: BSD-3-Clause-flex */ |
4 | | |
5 | | /* This file is part of flex. */ |
6 | | |
7 | | /* Redistribution and use in source and binary forms, with or without */ |
8 | | /* modification, are permitted provided that the following conditions */ |
9 | | /* are met: */ |
10 | | |
11 | | /* 1. Redistributions of source code must retain the above copyright */ |
12 | | /* notice, this list of conditions and the following disclaimer. */ |
13 | | /* 2. Redistributions in binary form must reproduce the above copyright */ |
14 | | /* notice, this list of conditions and the following disclaimer in the */ |
15 | | /* documentation and/or other materials provided with the distribution. */ |
16 | | |
17 | | /* Neither the name of the University nor the names of its contributors */ |
18 | | /* may be used to endorse or promote products derived from this software */ |
19 | | /* without specific prior written permission. */ |
20 | | |
21 | | /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ |
22 | | /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ |
23 | | /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ |
24 | | /* PURPOSE. */ |
25 | | |
26 | | #include "flexdef.h" |
27 | | |
28 | | |
29 | | regex_t regex_linedir; /**< matches line directives */ |
30 | | |
31 | | |
32 | | /** Initialize the regular expressions. |
33 | | * @return true upon success. |
34 | | */ |
35 | | bool flex_init_regex(const char *traceline_re) |
36 | 0 | { |
37 | 0 | if (traceline_re != NULL) |
38 | 0 | flex_regcomp(®ex_linedir, traceline_re, REG_EXTENDED); |
39 | 0 | return true; |
40 | 0 | } |
41 | | |
42 | | /** Compiles a regular expression or dies trying. |
43 | | * @param preg Same as for regcomp(). |
44 | | * @param regex Same as for regcomp(). |
45 | | * @param cflags Same as for regcomp(). |
46 | | */ |
47 | | void flex_regcomp(regex_t *preg, const char *regex, int cflags) |
48 | 0 | { |
49 | 0 | int err; |
50 | |
|
51 | 0 | memset (preg, 0, sizeof (regex_t)); |
52 | |
|
53 | 0 | if ((err = regcomp (preg, regex, cflags)) != 0) { |
54 | 0 | const size_t errbuf_sz = 200; |
55 | 0 | char *errbuf; |
56 | 0 | int n; |
57 | |
|
58 | 0 | errbuf = malloc(errbuf_sz * sizeof(char)); |
59 | 0 | if (!errbuf) |
60 | 0 | flexfatal(_("Unable to allocate buffer to report regcomp")); |
61 | 0 | n = snprintf(errbuf, errbuf_sz, "regcomp for \"%s\" failed: ", regex); |
62 | 0 | regerror(err, preg, errbuf+n, errbuf_sz-(size_t)n); |
63 | |
|
64 | 0 | flexfatal (errbuf); /* never returns - no need to free(errbuf) */ |
65 | 0 | } |
66 | 0 | } |
67 | | |
68 | | /** Extract a copy of the match, or NULL if no match. |
69 | | * @param m A match as returned by regexec(). |
70 | | * @param src The source string that was passed to regexec(). |
71 | | * @return The allocated string. |
72 | | */ |
73 | | char *regmatch_dup (regmatch_t * m, const char *src) |
74 | 0 | { |
75 | 0 | char *str; |
76 | 0 | size_t len; |
77 | |
|
78 | 0 | if (m == NULL || m->rm_so < 0 || m->rm_eo < m->rm_so) |
79 | 0 | return NULL; |
80 | 0 | len = (size_t) (m->rm_eo - m->rm_so); |
81 | 0 | str = malloc((len + 1) * sizeof(char)); |
82 | 0 | if (!str) |
83 | 0 | flexfatal(_("Unable to allocate a copy of the match")); |
84 | 0 | strncpy (str, src + m->rm_so, len); |
85 | 0 | str[len] = 0; |
86 | 0 | return str; |
87 | 0 | } |
88 | | |
89 | | /** Copy the match. |
90 | | * @param m A match as returned by regexec(). |
91 | | * @param dest The destination buffer. |
92 | | * @param src The source string that was passed to regexec(). |
93 | | * @return dest |
94 | | */ |
95 | | char *regmatch_cpy (regmatch_t * m, char *dest, const char *src) |
96 | 0 | { |
97 | 0 | if (m == NULL || m->rm_so < 0) { |
98 | 0 | if (dest) |
99 | 0 | dest[0] = '\0'; |
100 | 0 | return dest; |
101 | 0 | } |
102 | | |
103 | 0 | snprintf (dest, (size_t) regmatch_len(m), "%s", src + m->rm_so); |
104 | 0 | return dest; |
105 | 0 | } |
106 | | |
107 | | /** Get the length in characters of the match. |
108 | | * @param m A match as returned by regexec(). |
109 | | * @return The length of the match. |
110 | | */ |
111 | | int regmatch_len (regmatch_t * m) |
112 | 0 | { |
113 | 0 | if (m == NULL || m->rm_so < 0) { |
114 | 0 | return 0; |
115 | 0 | } |
116 | | |
117 | 0 | return m->rm_eo - m->rm_so; |
118 | 0 | } |
119 | | |
120 | | |
121 | | |
122 | | /** Convert a regmatch_t object to an integer using the strtol() function. |
123 | | * @param m A match as returned by regexec(). |
124 | | * @param src The source string that was passed to regexec(). |
125 | | * @param endptr Same as the second argument to strtol(). |
126 | | * @param base Same as the third argument to strtol(). |
127 | | * @return The converted integer or error (Return value is the same as for strtol()). |
128 | | */ |
129 | | int regmatch_strtol (regmatch_t * m, const char *src, char **endptr, |
130 | | int base) |
131 | 0 | { |
132 | 0 | int n = 0; |
133 | |
|
134 | 0 | #define bufsz 20 |
135 | 0 | char buf[bufsz]; |
136 | 0 | char *s; |
137 | |
|
138 | 0 | if (m == NULL || m->rm_so < 0) |
139 | 0 | return 0; |
140 | | |
141 | 0 | if (regmatch_len (m) < bufsz) |
142 | 0 | s = regmatch_cpy (m, buf, src); |
143 | 0 | else |
144 | 0 | s = regmatch_dup (m, src); |
145 | |
|
146 | 0 | n = (int) strtol (s, endptr, base); |
147 | |
|
148 | 0 | if (s != buf) |
149 | 0 | free (s); |
150 | |
|
151 | 0 | return n; |
152 | 0 | } |
153 | | |
154 | | /** Check for empty or non-existent match. |
155 | | * @param m A match as returned by regexec(). |
156 | | * @return false if match length is non-zero. |
157 | | * Note that reg_empty returns true even if match did not occur at all. |
158 | | */ |
159 | | bool regmatch_empty (regmatch_t * m) |
160 | 0 | { |
161 | 0 | return (m == NULL || m->rm_so < 0 || m->rm_so == m->rm_eo); |
162 | 0 | } |
163 | | |
164 | | /* vim:set expandtab cindent tabstop=4 softtabstop=4 shiftwidth=4 textwidth=0: */ |