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(®ex_linedir, REGEXP_LINEDIR, REG_EXTENDED);
41357f1050SThomas Veerman flex_regcomp(®ex_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