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