1 /* $OpenBSD: regex.c,v 1.3 2015/11/19 23:20:34 tedu 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 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*)malloc(errbuf_sz *sizeof(char)); 63 if (!errbuf) 64 flexfatal(_("Unable to allocate buffer to report regcomp")); 65 rxerr = (char*)malloc(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 *) malloc ((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 } 173