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