xref: /minix3/external/bsd/flex/dist/regex.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: regex.c,v 1.3 2014/10/30 18:44:05 christos Exp $	*/
2357f1050SThomas Veerman 
3357f1050SThomas Veerman /** regex - regular expression functions related to POSIX regex lib. */
4357f1050SThomas Veerman 
5357f1050SThomas Veerman /*  This file is part of flex. */
6357f1050SThomas Veerman 
7357f1050SThomas Veerman /*  Redistribution and use in source and binary forms, with or without */
8357f1050SThomas Veerman /*  modification, are permitted provided that the following conditions */
9357f1050SThomas Veerman /*  are met: */
10357f1050SThomas Veerman 
11357f1050SThomas Veerman /*  1. Redistributions of source code must retain the above copyright */
12357f1050SThomas Veerman /*     notice, this list of conditions and the following disclaimer. */
13357f1050SThomas Veerman /*  2. Redistributions in binary form must reproduce the above copyright */
14357f1050SThomas Veerman /*     notice, this list of conditions and the following disclaimer in the */
15357f1050SThomas Veerman /*     documentation and/or other materials provided with the distribution. */
16357f1050SThomas Veerman 
17357f1050SThomas Veerman /*  Neither the name of the University nor the names of its contributors */
18357f1050SThomas Veerman /*  may be used to endorse or promote products derived from this software */
19357f1050SThomas Veerman /*  without specific prior written permission. */
20357f1050SThomas Veerman 
21357f1050SThomas Veerman /*  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
22357f1050SThomas Veerman /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
23357f1050SThomas Veerman /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
24357f1050SThomas Veerman /*  PURPOSE. */
25357f1050SThomas Veerman #include "flexdef.h"
26*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: regex.c,v 1.3 2014/10/30 18:44:05 christos Exp $");
27357f1050SThomas Veerman 
28357f1050SThomas Veerman static const char* REGEXP_LINEDIR = "^#line ([[:digit:]]+) \"(.*)\"";
29357f1050SThomas Veerman static const char* REGEXP_BLANK_LINE = "^[[:space:]]*$";
30357f1050SThomas Veerman 
31357f1050SThomas Veerman regex_t regex_linedir; /**< matches line directives */
32357f1050SThomas Veerman regex_t regex_blank_line; /**< matches blank lines */
33357f1050SThomas Veerman 
34357f1050SThomas Veerman 
35357f1050SThomas Veerman /** Initialize the regular expressions.
36357f1050SThomas Veerman  * @return true upon success.
37357f1050SThomas Veerman  */
flex_init_regex(void)38357f1050SThomas Veerman bool flex_init_regex(void)
39357f1050SThomas Veerman {
40357f1050SThomas Veerman     flex_regcomp(&regex_linedir, REGEXP_LINEDIR, REG_EXTENDED);
41357f1050SThomas Veerman     flex_regcomp(&regex_blank_line, REGEXP_BLANK_LINE, REG_EXTENDED);
42357f1050SThomas Veerman 
43357f1050SThomas Veerman     return true;
44357f1050SThomas Veerman }
45357f1050SThomas Veerman 
46357f1050SThomas Veerman /** Compiles a regular expression or dies trying.
47357f1050SThomas Veerman  * @param preg  Same as for regcomp().
48357f1050SThomas Veerman  * @param regex Same as for regcomp().
49357f1050SThomas Veerman  * @param cflags Same as for regcomp().
50357f1050SThomas Veerman  */
flex_regcomp(regex_t * preg,const char * regex,int cflags)51357f1050SThomas Veerman void flex_regcomp(regex_t *preg, const char *regex, int cflags)
52357f1050SThomas Veerman {
53357f1050SThomas Veerman     int err;
54357f1050SThomas Veerman 
55357f1050SThomas Veerman 	memset (preg, 0, sizeof (regex_t));
56357f1050SThomas Veerman 
57357f1050SThomas Veerman 	if ((err = regcomp (preg, regex, cflags)) != 0) {
58357f1050SThomas Veerman         const int errbuf_sz = 200;
5984d9c625SLionel Sambuc         char *errbuf, *rxerr;
60357f1050SThomas Veerman 
61357f1050SThomas Veerman 		errbuf = (char*)flex_alloc(errbuf_sz *sizeof(char));
6284d9c625SLionel Sambuc 		if (!errbuf)
6384d9c625SLionel Sambuc 			flexfatal(_("Unable to allocate buffer to report regcomp"));
6484d9c625SLionel Sambuc 		rxerr = (char*)flex_alloc(errbuf_sz *sizeof(char));
6584d9c625SLionel Sambuc 		if (!rxerr)
6684d9c625SLionel Sambuc 			flexfatal(_("Unable to allocate buffer for regerror"));
6784d9c625SLionel Sambuc 		regerror (err, preg, rxerr, errbuf_sz);
6884d9c625SLionel Sambuc 		snprintf (errbuf, errbuf_sz, "regcomp for \"%s\" failed: %s", regex, rxerr);
69357f1050SThomas Veerman 
70357f1050SThomas Veerman 		flexfatal (errbuf);
71357f1050SThomas Veerman         free(errbuf);
7284d9c625SLionel Sambuc         free(rxerr);
73357f1050SThomas Veerman 	}
74357f1050SThomas Veerman }
75357f1050SThomas Veerman 
76357f1050SThomas Veerman /** Extract a copy of the match, or NULL if no match.
77357f1050SThomas Veerman  * @param m A match as returned by regexec().
78357f1050SThomas Veerman  * @param src The source string that was passed to regexec().
79357f1050SThomas Veerman  * @return The allocated string.
80357f1050SThomas Veerman  */
regmatch_dup(regmatch_t * m,const char * src)81357f1050SThomas Veerman char   *regmatch_dup (regmatch_t * m, const char *src)
82357f1050SThomas Veerman {
83357f1050SThomas Veerman 	char   *str;
84357f1050SThomas Veerman 	int     len;
85357f1050SThomas Veerman 
86357f1050SThomas Veerman 	if (m == NULL || m->rm_so < 0)
87357f1050SThomas Veerman 		return NULL;
88357f1050SThomas Veerman 	len = m->rm_eo - m->rm_so;
89357f1050SThomas Veerman 	str = (char *) flex_alloc ((len + 1) * sizeof (char));
9084d9c625SLionel Sambuc 	if (!str)
9184d9c625SLionel Sambuc 		flexfatal(_("Unable to allocate a copy of the match"));
92357f1050SThomas Veerman 	strncpy (str, src + m->rm_so, len);
93357f1050SThomas Veerman 	str[len] = 0;
94357f1050SThomas Veerman 	return str;
95357f1050SThomas Veerman }
96357f1050SThomas Veerman 
97357f1050SThomas Veerman /** Copy the match.
98357f1050SThomas Veerman  * @param m A match as returned by regexec().
99357f1050SThomas Veerman  * @param dest The destination buffer.
100357f1050SThomas Veerman  * @param src The source string that was passed to regexec().
101357f1050SThomas Veerman  * @return dest
102357f1050SThomas Veerman  */
regmatch_cpy(regmatch_t * m,char * dest,const char * src)103357f1050SThomas Veerman char   *regmatch_cpy (regmatch_t * m, char *dest, const char *src)
104357f1050SThomas Veerman {
105357f1050SThomas Veerman 	if (m == NULL || m->rm_so < 0) {
106357f1050SThomas Veerman 		if (dest)
107357f1050SThomas Veerman 			dest[0] = '\0';
108357f1050SThomas Veerman 		return dest;
109357f1050SThomas Veerman 	}
110357f1050SThomas Veerman 
111357f1050SThomas Veerman 	snprintf (dest, regmatch_len(m), "%s", src + m->rm_so);
112357f1050SThomas Veerman     return dest;
113357f1050SThomas Veerman }
114357f1050SThomas Veerman 
115357f1050SThomas Veerman /** Get the length in characters of the match.
116357f1050SThomas Veerman  * @param m A match as returned by regexec().
117357f1050SThomas Veerman  * @param src The source string that was passed to regexec().
118357f1050SThomas Veerman  * @return The length of the match.
119357f1050SThomas Veerman  */
regmatch_len(regmatch_t * m)120357f1050SThomas Veerman int regmatch_len (regmatch_t * m)
121357f1050SThomas Veerman {
122357f1050SThomas Veerman 	if (m == NULL || m->rm_so < 0) {
123357f1050SThomas Veerman 		return 0;
124357f1050SThomas Veerman 	}
125357f1050SThomas Veerman 
126357f1050SThomas Veerman 	return m->rm_eo - m->rm_so;
127357f1050SThomas Veerman }
128357f1050SThomas Veerman 
129357f1050SThomas Veerman 
130357f1050SThomas Veerman 
131357f1050SThomas Veerman /** Convert a regmatch_t object to an integer using the strtol() function.
132357f1050SThomas Veerman  * @param m A match as returned by regexec().
133357f1050SThomas Veerman  * @param src The source string that was passed to regexec().
134357f1050SThomas Veerman  * @param endptr Same as the second argument to strtol().
135357f1050SThomas Veerman  * @param base   Same as the third argument to strtol().
136357f1050SThomas Veerman  * @return The converted integer or error (Return value is the same as for strtol()).
137357f1050SThomas Veerman  */
regmatch_strtol(regmatch_t * m,const char * src,char ** endptr,int base)138357f1050SThomas Veerman int regmatch_strtol (regmatch_t * m, const char *src, char **endptr,
139357f1050SThomas Veerman 		     int base)
140357f1050SThomas Veerman {
141357f1050SThomas Veerman 	int     n = 0;
142357f1050SThomas Veerman 
143357f1050SThomas Veerman #define bufsz 20
144357f1050SThomas Veerman 	char    buf[bufsz];
145357f1050SThomas Veerman 	char   *s;
146357f1050SThomas Veerman 
147357f1050SThomas Veerman 	if (m == NULL || m->rm_so < 0)
148357f1050SThomas Veerman 		return 0;
149357f1050SThomas Veerman 
150357f1050SThomas Veerman 	if (regmatch_len (m) < bufsz)
151357f1050SThomas Veerman 		s = regmatch_cpy (m, buf, src);
152357f1050SThomas Veerman 	else
153357f1050SThomas Veerman 		s = regmatch_dup (m, src);
154357f1050SThomas Veerman 
155357f1050SThomas Veerman 	n = strtol (s, endptr, base);
156357f1050SThomas Veerman 
157357f1050SThomas Veerman 	if (s != buf)
158357f1050SThomas Veerman 		free (s);
159357f1050SThomas Veerman 
160357f1050SThomas Veerman 	return n;
161357f1050SThomas Veerman }
162357f1050SThomas Veerman 
163357f1050SThomas Veerman /** Check for empty or non-existent match.
164357f1050SThomas Veerman  * @param m A match as returned by regexec().
165357f1050SThomas Veerman  * @return false if match length is non-zero.
166357f1050SThomas Veerman  * Note that reg_empty returns true even if match did not occur at all.
167357f1050SThomas Veerman  */
regmatch_empty(regmatch_t * m)168357f1050SThomas Veerman bool regmatch_empty (regmatch_t * m)
169357f1050SThomas Veerman {
170357f1050SThomas Veerman 	return (m == NULL || m->rm_so < 0 || m->rm_so == m->rm_eo);
171357f1050SThomas Veerman }
172357f1050SThomas Veerman 
173357f1050SThomas Veerman /* vim:set expandtab cindent tabstop=4 softtabstop=4 shiftwidth=4 textwidth=0: */
174