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