]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/flex/src/regex.c
MFV: r362286
[FreeBSD/FreeBSD.git] / contrib / flex / src / regex.c
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  */
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  */
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 size_t errbuf_sz = 200;
58                 char *errbuf;
59                 int n;
60
61                 errbuf = malloc(errbuf_sz * sizeof(char));
62                 if (!errbuf)
63                         flexfatal(_("Unable to allocate buffer to report regcomp"));
64                 n = snprintf(errbuf, errbuf_sz, "regcomp for \"%s\" failed: ", regex);
65                 regerror(err, preg, errbuf+n, errbuf_sz-(size_t)n);
66
67                 flexfatal (errbuf); /* never returns - no need to free(errbuf) */
68         }
69 }
70
71 /** Extract a copy of the match, or NULL if no match.
72  * @param m A match as returned by regexec().
73  * @param src The source string that was passed to regexec().
74  * @return The allocated string.
75  */
76 char   *regmatch_dup (regmatch_t * m, const char *src)
77 {
78         char   *str;
79         size_t  len;
80
81         if (m == NULL || m->rm_so < 0 || m->rm_eo < m->rm_so)
82                 return NULL;
83         len = (size_t) (m->rm_eo - m->rm_so);
84         str = malloc((len + 1) * sizeof(char));
85         if (!str)
86                 flexfatal(_("Unable to allocate a copy of the match"));
87         strncpy (str, src + m->rm_so, len);
88         str[len] = 0;
89         return str;
90 }
91
92 /** Copy the match.
93  * @param m A match as returned by regexec().
94  * @param dest The destination buffer.
95  * @param src The source string that was passed to regexec().
96  * @return dest
97  */
98 char   *regmatch_cpy (regmatch_t * m, char *dest, const char *src)
99 {
100         if (m == NULL || m->rm_so < 0) {
101                 if (dest)
102                         dest[0] = '\0';
103                 return dest;
104         }
105
106         snprintf (dest, (size_t) regmatch_len(m), "%s", src + m->rm_so);
107     return dest;
108 }
109
110 /** Get the length in characters of the match.
111  * @param m A match as returned by regexec().
112  * @return The length of the match.
113  */
114 int regmatch_len (regmatch_t * m)
115 {
116         if (m == NULL || m->rm_so < 0) {
117                 return 0;
118         }
119
120         return m->rm_eo - m->rm_so;
121 }
122
123
124
125 /** Convert a regmatch_t object to an integer using the strtol() function.
126  * @param m A match as returned by regexec().
127  * @param src The source string that was passed to regexec().
128  * @param endptr Same as the second argument to strtol().
129  * @param base   Same as the third argument to strtol().
130  * @return The converted integer or error (Return value is the same as for strtol()).
131  */
132 int regmatch_strtol (regmatch_t * m, const char *src, char **endptr,
133                      int base)
134 {
135         int     n = 0;
136
137 #define bufsz 20
138         char    buf[bufsz];
139         char   *s;
140
141         if (m == NULL || m->rm_so < 0)
142                 return 0;
143
144         if (regmatch_len (m) < bufsz)
145                 s = regmatch_cpy (m, buf, src);
146         else
147                 s = regmatch_dup (m, src);
148
149         n = (int) strtol (s, endptr, base);
150
151         if (s != buf)
152                 free (s);
153
154         return n;
155 }
156
157 /** Check for empty or non-existent match.
158  * @param m A match as returned by regexec().
159  * @return false if match length is non-zero.
160  * Note that reg_empty returns true even if match did not occur at all.
161  */
162 bool regmatch_empty (regmatch_t * m)
163 {
164         return (m == NULL || m->rm_so < 0 || m->rm_so == m->rm_eo);
165 }
166
167 /* vim:set expandtab cindent tabstop=4 softtabstop=4 shiftwidth=4 textwidth=0: */