GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/lex/regex.c Lines: 29 50 58.0 %
Date: 2017-11-07 Branches: 12 34 35.3 %

Line Branch Exec Source
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
{
41
60
    flex_regcomp(&regex_linedir, REGEXP_LINEDIR, REG_EXTENDED);
42
30
    flex_regcomp(&regex_blank_line, REGEXP_BLANK_LINE, REG_EXTENDED);
43
44
30
    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
{
54
    int err;
55
56
120
	memset (preg, 0, sizeof (regex_t));
57
58
60
	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
60
}
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
{
84
	char   *str;
85
	int     len;
86
87

1974
	if (m == NULL || m->rm_so < 0)
88
		return NULL;
89
658
	len = m->rm_eo - m->rm_so;
90
658
	str = (char *) malloc ((len + 1) * sizeof (char));
91
658
	if (!str)
92
		flexfatal(_("Unable to allocate a copy of the match"));
93
658
	strncpy (str, src + m->rm_so, len);
94
658
	str[len] = 0;
95
658
	return str;
96
658
}
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
{
106

1974
	if (m == NULL || m->rm_so < 0) {
107
		if (dest)
108
			dest[0] = '\0';
109
		return dest;
110
	}
111
112
658
	snprintf (dest, regmatch_len(m), "%s", src + m->rm_so);
113
658
    return dest;
114
658
}
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
{
123

3948
	if (m == NULL || m->rm_so < 0) {
124
		return 0;
125
	}
126
127
1316
	return m->rm_eo - m->rm_so;
128
1316
}
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
{
142
	int     n = 0;
143
144
#define bufsz 20
145
1316
	char    buf[bufsz];
146
	char   *s;
147
148

1316
	if (m == NULL || m->rm_so < 0)
149
		return 0;
150
151
658
	if (regmatch_len (m) < bufsz)
152
658
		s = regmatch_cpy (m, buf, src);
153
	else
154
		s = regmatch_dup (m, src);
155
156
658
	n = strtol (s, endptr, base);
157
158
658
	if (s != buf)
159
		free (s);
160
161
658
	return n;
162
658
}
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
}