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