1 /* $NetBSD: regex.c,v 1.2 2016/01/09 17:38:57 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.2 2016/01/09 17:38:57 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 * @return The length of the match. 118 */ 119 int 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 */ 137 int 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 */ 167 bool 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