1228072Sbapt/** regex - regular expression functions related to POSIX regex lib. */ 2228072Sbapt 3228072Sbapt/* This file is part of flex. */ 4228072Sbapt 5228072Sbapt/* Redistribution and use in source and binary forms, with or without */ 6228072Sbapt/* modification, are permitted provided that the following conditions */ 7228072Sbapt/* are met: */ 8228072Sbapt 9228072Sbapt/* 1. Redistributions of source code must retain the above copyright */ 10228072Sbapt/* notice, this list of conditions and the following disclaimer. */ 11228072Sbapt/* 2. Redistributions in binary form must reproduce the above copyright */ 12228072Sbapt/* notice, this list of conditions and the following disclaimer in the */ 13228072Sbapt/* documentation and/or other materials provided with the distribution. */ 14228072Sbapt 15228072Sbapt/* Neither the name of the University nor the names of its contributors */ 16228072Sbapt/* may be used to endorse or promote products derived from this software */ 17228072Sbapt/* without specific prior written permission. */ 18228072Sbapt 19228072Sbapt/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ 20228072Sbapt/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ 21228072Sbapt/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ 22228072Sbapt/* PURPOSE. */ 23228072Sbapt 24228072Sbapt#include "flexdef.h" 25228072Sbapt 26228072Sbapt 27228072Sbaptstatic const char* REGEXP_LINEDIR = "^#line ([[:digit:]]+) \"(.*)\""; 28228072Sbaptstatic const char* REGEXP_BLANK_LINE = "^[[:space:]]*$"; 29228072Sbapt 30228072Sbaptregex_t regex_linedir; /**< matches line directives */ 31228072Sbaptregex_t regex_blank_line; /**< matches blank lines */ 32228072Sbapt 33228072Sbapt 34228072Sbapt/** Initialize the regular expressions. 35228072Sbapt * @return true upon success. 36228072Sbapt */ 37228072Sbaptbool flex_init_regex(void) 38228072Sbapt{ 39228072Sbapt flex_regcomp(®ex_linedir, REGEXP_LINEDIR, REG_EXTENDED); 40228072Sbapt flex_regcomp(®ex_blank_line, REGEXP_BLANK_LINE, REG_EXTENDED); 41228072Sbapt 42228072Sbapt return true; 43228072Sbapt} 44228072Sbapt 45228072Sbapt/** Compiles a regular expression or dies trying. 46228072Sbapt * @param preg Same as for regcomp(). 47228072Sbapt * @param regex Same as for regcomp(). 48228072Sbapt * @param cflags Same as for regcomp(). 49228072Sbapt */ 50228072Sbaptvoid flex_regcomp(regex_t *preg, const char *regex, int cflags) 51228072Sbapt{ 52228072Sbapt int err; 53228072Sbapt 54228072Sbapt memset (preg, 0, sizeof (regex_t)); 55228072Sbapt 56228072Sbapt if ((err = regcomp (preg, regex, cflags)) != 0) { 57228072Sbapt const int errbuf_sz = 200; 58250125Sjkim char *errbuf, *rxerr; 59228072Sbapt 60250125Sjkim errbuf = (char*)flex_alloc(errbuf_sz *sizeof(char)); 61250125Sjkim if (!errbuf) 62250125Sjkim flexfatal(_("Unable to allocate buffer to report regcomp")); 63250125Sjkim rxerr = (char*)flex_alloc(errbuf_sz *sizeof(char)); 64250125Sjkim if (!rxerr) 65250125Sjkim flexfatal(_("Unable to allocate buffer for regerror")); 66250125Sjkim regerror (err, preg, rxerr, errbuf_sz); 67250125Sjkim snprintf (errbuf, errbuf_sz, "regcomp for \"%s\" failed: %s", regex, rxerr); 68228072Sbapt 69228072Sbapt flexfatal (errbuf); 70228072Sbapt free(errbuf); 71250125Sjkim free(rxerr); 72228072Sbapt } 73228072Sbapt} 74228072Sbapt 75228072Sbapt/** Extract a copy of the match, or NULL if no match. 76228072Sbapt * @param m A match as returned by regexec(). 77228072Sbapt * @param src The source string that was passed to regexec(). 78228072Sbapt * @return The allocated string. 79228072Sbapt */ 80228072Sbaptchar *regmatch_dup (regmatch_t * m, const char *src) 81228072Sbapt{ 82228072Sbapt char *str; 83228072Sbapt int len; 84228072Sbapt 85228072Sbapt if (m == NULL || m->rm_so < 0) 86228072Sbapt return NULL; 87228072Sbapt len = m->rm_eo - m->rm_so; 88228072Sbapt str = (char *) flex_alloc ((len + 1) * sizeof (char)); 89250125Sjkim if (!str) 90250125Sjkim flexfatal(_("Unable to allocate a copy of the match")); 91228072Sbapt strncpy (str, src + m->rm_so, len); 92228072Sbapt str[len] = 0; 93228072Sbapt return str; 94228072Sbapt} 95228072Sbapt 96228072Sbapt/** Copy the match. 97228072Sbapt * @param m A match as returned by regexec(). 98228072Sbapt * @param dest The destination buffer. 99228072Sbapt * @param src The source string that was passed to regexec(). 100228072Sbapt * @return dest 101228072Sbapt */ 102228072Sbaptchar *regmatch_cpy (regmatch_t * m, char *dest, const char *src) 103228072Sbapt{ 104228072Sbapt if (m == NULL || m->rm_so < 0) { 105228072Sbapt if (dest) 106228072Sbapt dest[0] = '\0'; 107228072Sbapt return dest; 108228072Sbapt } 109228072Sbapt 110228072Sbapt snprintf (dest, regmatch_len(m), "%s", src + m->rm_so); 111228072Sbapt return dest; 112228072Sbapt} 113228072Sbapt 114228072Sbapt/** Get the length in characters of the match. 115228072Sbapt * @param m A match as returned by regexec(). 116228072Sbapt * @param src The source string that was passed to regexec(). 117228072Sbapt * @return The length of the match. 118228072Sbapt */ 119228072Sbaptint regmatch_len (regmatch_t * m) 120228072Sbapt{ 121228072Sbapt if (m == NULL || m->rm_so < 0) { 122228072Sbapt return 0; 123228072Sbapt } 124228072Sbapt 125228072Sbapt return m->rm_eo - m->rm_so; 126228072Sbapt} 127228072Sbapt 128228072Sbapt 129228072Sbapt 130228072Sbapt/** Convert a regmatch_t object to an integer using the strtol() function. 131228072Sbapt * @param m A match as returned by regexec(). 132228072Sbapt * @param src The source string that was passed to regexec(). 133228072Sbapt * @param endptr Same as the second argument to strtol(). 134228072Sbapt * @param base Same as the third argument to strtol(). 135228072Sbapt * @return The converted integer or error (Return value is the same as for strtol()). 136228072Sbapt */ 137228072Sbaptint regmatch_strtol (regmatch_t * m, const char *src, char **endptr, 138228072Sbapt int base) 139228072Sbapt{ 140228072Sbapt int n = 0; 141228072Sbapt 142228072Sbapt#define bufsz 20 143228072Sbapt char buf[bufsz]; 144228072Sbapt char *s; 145228072Sbapt 146228072Sbapt if (m == NULL || m->rm_so < 0) 147228072Sbapt return 0; 148228072Sbapt 149228072Sbapt if (regmatch_len (m) < bufsz) 150228072Sbapt s = regmatch_cpy (m, buf, src); 151228072Sbapt else 152228072Sbapt s = regmatch_dup (m, src); 153228072Sbapt 154228072Sbapt n = strtol (s, endptr, base); 155228072Sbapt 156228072Sbapt if (s != buf) 157228072Sbapt free (s); 158228072Sbapt 159228072Sbapt return n; 160228072Sbapt} 161228072Sbapt 162228072Sbapt/** Check for empty or non-existent match. 163228072Sbapt * @param m A match as returned by regexec(). 164228072Sbapt * @return false if match length is non-zero. 165228072Sbapt * Note that reg_empty returns true even if match did not occur at all. 166228072Sbapt */ 167228072Sbaptbool regmatch_empty (regmatch_t * m) 168228072Sbapt{ 169228072Sbapt return (m == NULL || m->rm_so < 0 || m->rm_so == m->rm_eo); 170228072Sbapt} 171228072Sbapt 172228072Sbapt/* vim:set expandtab cindent tabstop=4 softtabstop=4 shiftwidth=4 textwidth=0: */ 173