(root)/
flex-2.6.4/
src/
regex.c
       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(&regex_linedir, REGEXP_LINEDIR, REG_EXTENDED);
      40      flex_regcomp(&regex_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: */