1 |
|
|
/* $OpenBSD: regex.c,v 1.3 2015/11/19 23:20:34 tedu Exp $ */ |
2 |
|
|
|
3 |
|
|
/** regex - regular expression functions related to POSIX regex lib. */ |
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 |
|
|
static const char* REGEXP_LINEDIR = "^#line ([[:digit:]]+) \"(.*)\""; |
30 |
|
|
static const char* REGEXP_BLANK_LINE = "^[[:space:]]*$"; |
31 |
|
|
|
32 |
|
|
regex_t regex_linedir; /**< matches line directives */ |
33 |
|
|
regex_t regex_blank_line; /**< matches blank lines */ |
34 |
|
|
|
35 |
|
|
|
36 |
|
|
/** Initialize the regular expressions. |
37 |
|
|
* @return true upon success. |
38 |
|
|
*/ |
39 |
|
|
bool flex_init_regex(void) |
40 |
|
5 |
{ |
41 |
|
5 |
flex_regcomp(®ex_linedir, REGEXP_LINEDIR, REG_EXTENDED); |
42 |
|
5 |
flex_regcomp(®ex_blank_line, REGEXP_BLANK_LINE, REG_EXTENDED); |
43 |
|
|
|
44 |
|
5 |
return true; |
45 |
|
|
} |
46 |
|
|
|
47 |
|
|
/** Compiles a regular expression or dies trying. |
48 |
|
|
* @param preg Same as for regcomp(). |
49 |
|
|
* @param regex Same as for regcomp(). |
50 |
|
|
* @param cflags Same as for regcomp(). |
51 |
|
|
*/ |
52 |
|
|
void flex_regcomp(regex_t *preg, const char *regex, int cflags) |
53 |
|
10 |
{ |
54 |
|
|
int err; |
55 |
|
|
|
56 |
|
10 |
memset (preg, 0, sizeof (regex_t)); |
57 |
|
|
|
58 |
✗✓ |
10 |
if ((err = regcomp (preg, regex, cflags)) != 0) { |
59 |
|
|
const int errbuf_sz = 200; |
60 |
|
|
char *errbuf, *rxerr; |
61 |
|
|
|
62 |
|
|
errbuf = (char*)malloc(errbuf_sz *sizeof(char)); |
63 |
|
|
if (!errbuf) |
64 |
|
|
flexfatal(_("Unable to allocate buffer to report regcomp")); |
65 |
|
|
rxerr = (char*)malloc(errbuf_sz *sizeof(char)); |
66 |
|
|
if (!rxerr) |
67 |
|
|
flexfatal(_("Unable to allocate buffer for regerror")); |
68 |
|
|
regerror (err, preg, rxerr, errbuf_sz); |
69 |
|
|
snprintf (errbuf, errbuf_sz, "regcomp for \"%s\" failed: %s", regex, rxerr); |
70 |
|
|
|
71 |
|
|
flexfatal (errbuf); |
72 |
|
|
free(errbuf); |
73 |
|
|
free(rxerr); |
74 |
|
|
} |
75 |
|
10 |
} |
76 |
|
|
|
77 |
|
|
/** Extract a copy of the match, or NULL if no match. |
78 |
|
|
* @param m A match as returned by regexec(). |
79 |
|
|
* @param src The source string that was passed to regexec(). |
80 |
|
|
* @return The allocated string. |
81 |
|
|
*/ |
82 |
|
|
char *regmatch_dup (regmatch_t * m, const char *src) |
83 |
|
222 |
{ |
84 |
|
|
char *str; |
85 |
|
|
int len; |
86 |
|
|
|
87 |
✓✗✗✓
|
222 |
if (m == NULL || m->rm_so < 0) |
88 |
|
|
return NULL; |
89 |
|
222 |
len = m->rm_eo - m->rm_so; |
90 |
|
222 |
str = (char *) malloc ((len + 1) * sizeof (char)); |
91 |
✗✓ |
222 |
if (!str) |
92 |
|
|
flexfatal(_("Unable to allocate a copy of the match")); |
93 |
|
222 |
strncpy (str, src + m->rm_so, len); |
94 |
|
222 |
str[len] = 0; |
95 |
|
222 |
return str; |
96 |
|
|
} |
97 |
|
|
|
98 |
|
|
/** Copy the match. |
99 |
|
|
* @param m A match as returned by regexec(). |
100 |
|
|
* @param dest The destination buffer. |
101 |
|
|
* @param src The source string that was passed to regexec(). |
102 |
|
|
* @return dest |
103 |
|
|
*/ |
104 |
|
|
char *regmatch_cpy (regmatch_t * m, char *dest, const char *src) |
105 |
|
222 |
{ |
106 |
✓✗✗✓
|
222 |
if (m == NULL || m->rm_so < 0) { |
107 |
|
|
if (dest) |
108 |
|
|
dest[0] = '\0'; |
109 |
|
|
return dest; |
110 |
|
|
} |
111 |
|
|
|
112 |
|
222 |
snprintf (dest, regmatch_len(m), "%s", src + m->rm_so); |
113 |
|
222 |
return dest; |
114 |
|
|
} |
115 |
|
|
|
116 |
|
|
/** Get the length in characters of the match. |
117 |
|
|
* @param m A match as returned by regexec(). |
118 |
|
|
* @param src The source string that was passed to regexec(). |
119 |
|
|
* @return The length of the match. |
120 |
|
|
*/ |
121 |
|
|
int regmatch_len (regmatch_t * m) |
122 |
|
444 |
{ |
123 |
✓✗✗✓
|
444 |
if (m == NULL || m->rm_so < 0) { |
124 |
|
|
return 0; |
125 |
|
|
} |
126 |
|
|
|
127 |
|
444 |
return m->rm_eo - m->rm_so; |
128 |
|
|
} |
129 |
|
|
|
130 |
|
|
|
131 |
|
|
|
132 |
|
|
/** Convert a regmatch_t object to an integer using the strtol() function. |
133 |
|
|
* @param m A match as returned by regexec(). |
134 |
|
|
* @param src The source string that was passed to regexec(). |
135 |
|
|
* @param endptr Same as the second argument to strtol(). |
136 |
|
|
* @param base Same as the third argument to strtol(). |
137 |
|
|
* @return The converted integer or error (Return value is the same as for strtol()). |
138 |
|
|
*/ |
139 |
|
|
int regmatch_strtol (regmatch_t * m, const char *src, char **endptr, |
140 |
|
|
int base) |
141 |
|
222 |
{ |
142 |
|
222 |
int n = 0; |
143 |
|
|
|
144 |
|
|
#define bufsz 20 |
145 |
|
|
char buf[bufsz]; |
146 |
|
|
char *s; |
147 |
|
|
|
148 |
✓✗✗✓
|
222 |
if (m == NULL || m->rm_so < 0) |
149 |
|
|
return 0; |
150 |
|
|
|
151 |
✓✗ |
222 |
if (regmatch_len (m) < bufsz) |
152 |
|
222 |
s = regmatch_cpy (m, buf, src); |
153 |
|
|
else |
154 |
|
|
s = regmatch_dup (m, src); |
155 |
|
|
|
156 |
|
222 |
n = strtol (s, endptr, base); |
157 |
|
|
|
158 |
✗✓ |
222 |
if (s != buf) |
159 |
|
|
free (s); |
160 |
|
|
|
161 |
|
222 |
return n; |
162 |
|
|
} |
163 |
|
|
|
164 |
|
|
/** Check for empty or non-existent match. |
165 |
|
|
* @param m A match as returned by regexec(). |
166 |
|
|
* @return false if match length is non-zero. |
167 |
|
|
* Note that reg_empty returns true even if match did not occur at all. |
168 |
|
|
*/ |
169 |
|
|
bool regmatch_empty (regmatch_t * m) |
170 |
|
|
{ |
171 |
|
|
return (m == NULL || m->rm_so < 0 || m->rm_so == m->rm_eo); |
172 |
|
|
} |