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