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