Annotation of src/usr.bin/lex/regex.c, Revision 1.2
1.2 ! tedu 1: /* $OpenBSD: regex.c,v 1.1 2015/11/19 19:43:40 tedu Exp $ */
1.1 tedu 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:
29: static const char* REGEXP_LINEDIR = "^#line ([[:digit:]]+) \"(.*)\"";
30: static const char* REGEXP_BLANK_LINE = "^[[:space:]]*$";
31:
32: regex_t regex_linedir; /**< matches line directives */
33: regex_t regex_blank_line; /**< matches blank lines */
34:
35:
36: /** Initialize the regular expressions.
37: * @return true upon success.
38: */
39: bool flex_init_regex(void)
40: {
41: flex_regcomp(®ex_linedir, REGEXP_LINEDIR, REG_EXTENDED);
42: flex_regcomp(®ex_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: */
52: void 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, *rxerr;
61:
62: errbuf = (char*)flex_alloc(errbuf_sz *sizeof(char));
63: if (!errbuf)
64: flexfatal(_("Unable to allocate buffer to report regcomp"));
65: rxerr = (char*)flex_alloc(errbuf_sz *sizeof(char));
66: if (!rxerr)
67: flexfatal(_("Unable to allocate buffer for regerror"));
68: regerror (err, preg, rxerr, errbuf_sz);
69: snprintf (errbuf, errbuf_sz, "regcomp for \"%s\" failed: %s", regex, rxerr);
70:
71: flexfatal (errbuf);
72: free(errbuf);
73: free(rxerr);
74: }
75: }
76:
77: /** Extract a copy of the match, or NULL if no match.
78: * @param m A match as returned by regexec().
79: * @param src The source string that was passed to regexec().
80: * @return The allocated string.
81: */
82: char *regmatch_dup (regmatch_t * m, const char *src)
83: {
84: char *str;
85: int len;
86:
87: if (m == NULL || m->rm_so < 0)
88: return NULL;
89: len = m->rm_eo - m->rm_so;
90: str = (char *) flex_alloc ((len + 1) * sizeof (char));
91: if (!str)
92: flexfatal(_("Unable to allocate a copy of the match"));
93: strncpy (str, src + m->rm_so, len);
94: str[len] = 0;
95: return str;
96: }
97:
98: /** Copy the match.
99: * @param m A match as returned by regexec().
100: * @param dest The destination buffer.
101: * @param src The source string that was passed to regexec().
102: * @return dest
103: */
104: char *regmatch_cpy (regmatch_t * m, char *dest, const char *src)
105: {
106: if (m == NULL || m->rm_so < 0) {
107: if (dest)
108: dest[0] = '\0';
109: return dest;
110: }
111:
112: snprintf (dest, regmatch_len(m), "%s", src + m->rm_so);
113: return dest;
114: }
115:
116: /** Get the length in characters of the match.
117: * @param m A match as returned by regexec().
118: * @param src The source string that was passed to regexec().
119: * @return The length of the match.
120: */
121: int regmatch_len (regmatch_t * m)
122: {
123: if (m == NULL || m->rm_so < 0) {
124: return 0;
125: }
126:
127: return m->rm_eo - m->rm_so;
128: }
129:
130:
131:
132: /** Convert a regmatch_t object to an integer using the strtol() function.
133: * @param m A match as returned by regexec().
134: * @param src The source string that was passed to regexec().
135: * @param endptr Same as the second argument to strtol().
136: * @param base Same as the third argument to strtol().
137: * @return The converted integer or error (Return value is the same as for strtol()).
138: */
139: int regmatch_strtol (regmatch_t * m, const char *src, char **endptr,
140: int base)
141: {
142: int n = 0;
143:
144: #define bufsz 20
145: char buf[bufsz];
146: char *s;
147:
148: if (m == NULL || m->rm_so < 0)
149: return 0;
150:
151: if (regmatch_len (m) < bufsz)
152: s = regmatch_cpy (m, buf, src);
153: else
154: s = regmatch_dup (m, src);
155:
156: n = strtol (s, endptr, base);
157:
158: if (s != buf)
159: free (s);
160:
161: return n;
162: }
163:
164: /** Check for empty or non-existent match.
165: * @param m A match as returned by regexec().
166: * @return false if match length is non-zero.
167: * Note that reg_empty returns true even if match did not occur at all.
168: */
169: bool regmatch_empty (regmatch_t * m)
170: {
171: return (m == NULL || m->rm_so < 0 || m->rm_so == m->rm_eo);
172: }