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