regex.c revision 250873
1/** regex - regular expression functions related to POSIX regex lib. */ 2 3/* This file is part of flex. */ 4 5/* Redistribution and use in source and binary forms, with or without */ 6/* modification, are permitted provided that the following conditions */ 7/* are met: */ 8 9/* 1. Redistributions of source code must retain the above copyright */ 10/* notice, this list of conditions and the following disclaimer. */ 11/* 2. Redistributions in binary form must reproduce the above copyright */ 12/* notice, this list of conditions and the following disclaimer in the */ 13/* documentation and/or other materials provided with the distribution. */ 14 15/* Neither the name of the University nor the names of its contributors */ 16/* may be used to endorse or promote products derived from this software */ 17/* without specific prior written permission. */ 18 19/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ 20/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ 21/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ 22/* PURPOSE. */ 23 24#include "flexdef.h" 25 26 27static const char* REGEXP_LINEDIR = "^#line ([[:digit:]]+) \"(.*)\""; 28static const char* REGEXP_BLANK_LINE = "^[[:space:]]*$"; 29 30regex_t regex_linedir; /**< matches line directives */ 31regex_t regex_blank_line; /**< matches blank lines */ 32 33 34/** Initialize the regular expressions. 35 * @return true upon success. 36 */ 37bool flex_init_regex(void) 38{ 39 flex_regcomp(®ex_linedir, REGEXP_LINEDIR, REG_EXTENDED); 40 flex_regcomp(®ex_blank_line, REGEXP_BLANK_LINE, REG_EXTENDED); 41 42 return true; 43} 44 45/** Compiles a regular expression or dies trying. 46 * @param preg Same as for regcomp(). 47 * @param regex Same as for regcomp(). 48 * @param cflags Same as for regcomp(). 49 */ 50void flex_regcomp(regex_t *preg, const char *regex, int cflags) 51{ 52 int err; 53 54 memset (preg, 0, sizeof (regex_t)); 55 56 if ((err = regcomp (preg, regex, cflags)) != 0) { 57 const int errbuf_sz = 200; 58 char *errbuf, *rxerr; 59 60 errbuf = (char*)flex_alloc(errbuf_sz *sizeof(char)); 61 if (!errbuf) 62 flexfatal(_("Unable to allocate buffer to report regcomp")); 63 rxerr = (char*)flex_alloc(errbuf_sz *sizeof(char)); 64 if (!rxerr) 65 flexfatal(_("Unable to allocate buffer for regerror")); 66 regerror (err, preg, rxerr, errbuf_sz); 67 snprintf (errbuf, errbuf_sz, "regcomp for \"%s\" failed: %s", regex, rxerr); 68 69 flexfatal (errbuf); 70 free(errbuf); 71 free(rxerr); 72 } 73} 74 75/** Extract a copy of the match, or NULL if no match. 76 * @param m A match as returned by regexec(). 77 * @param src The source string that was passed to regexec(). 78 * @return The allocated string. 79 */ 80char *regmatch_dup (regmatch_t * m, const char *src) 81{ 82 char *str; 83 int len; 84 85 if (m == NULL || m->rm_so < 0) 86 return NULL; 87 len = m->rm_eo - m->rm_so; 88 str = (char *) flex_alloc ((len + 1) * sizeof (char)); 89 if (!str) 90 flexfatal(_("Unable to allocate a copy of the match")); 91 strncpy (str, src + m->rm_so, len); 92 str[len] = 0; 93 return str; 94} 95 96/** Copy the match. 97 * @param m A match as returned by regexec(). 98 * @param dest The destination buffer. 99 * @param src The source string that was passed to regexec(). 100 * @return dest 101 */ 102char *regmatch_cpy (regmatch_t * m, char *dest, const char *src) 103{ 104 if (m == NULL || m->rm_so < 0) { 105 if (dest) 106 dest[0] = '\0'; 107 return dest; 108 } 109 110 snprintf (dest, regmatch_len(m), "%s", src + m->rm_so); 111 return dest; 112} 113 114/** Get the length in characters of the match. 115 * @param m A match as returned by regexec(). 116 * @param src The source string that was passed to regexec(). 117 * @return The length of the match. 118 */ 119int regmatch_len (regmatch_t * m) 120{ 121 if (m == NULL || m->rm_so < 0) { 122 return 0; 123 } 124 125 return m->rm_eo - m->rm_so; 126} 127 128 129 130/** Convert a regmatch_t object to an integer using the strtol() function. 131 * @param m A match as returned by regexec(). 132 * @param src The source string that was passed to regexec(). 133 * @param endptr Same as the second argument to strtol(). 134 * @param base Same as the third argument to strtol(). 135 * @return The converted integer or error (Return value is the same as for strtol()). 136 */ 137int regmatch_strtol (regmatch_t * m, const char *src, char **endptr, 138 int base) 139{ 140 int n = 0; 141 142#define bufsz 20 143 char buf[bufsz]; 144 char *s; 145 146 if (m == NULL || m->rm_so < 0) 147 return 0; 148 149 if (regmatch_len (m) < bufsz) 150 s = regmatch_cpy (m, buf, src); 151 else 152 s = regmatch_dup (m, src); 153 154 n = strtol (s, endptr, base); 155 156 if (s != buf) 157 free (s); 158 159 return n; 160} 161 162/** Check for empty or non-existent match. 163 * @param m A match as returned by regexec(). 164 * @return false if match length is non-zero. 165 * Note that reg_empty returns true even if match did not occur at all. 166 */ 167bool regmatch_empty (regmatch_t * m) 168{ 169 return (m == NULL || m->rm_so < 0 || m->rm_so == m->rm_eo); 170} 171 172/* vim:set expandtab cindent tabstop=4 softtabstop=4 shiftwidth=4 textwidth=0: */ 173