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