| /* |
| * shmatch.c -- shell interface to posix regular expression matching. |
| */ |
| |
| /* Copyright (C) 2003 Free Software Foundation, Inc. |
| |
| This file is part of GNU Bash, the Bourne Again SHell. |
| |
| Bash is free software: you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| Bash is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with Bash. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| # include <config.h> |
| #endif |
| |
| #if defined (HAVE_POSIX_REGEXP) |
| |
| #ifdef HAVE_UNISTD_H |
| # include <unistd.h> |
| #endif |
| |
| #include "bashansi.h" |
| |
| #include <stdio.h> |
| #include <regex.h> |
| |
| #include "shell.h" |
| #include "variables.h" |
| #include "externs.h" |
| |
| extern int glob_ignore_case, match_ignore_case; |
| |
| int |
| sh_regmatch (string, pattern, flags) |
| const char *string; |
| const char *pattern; |
| int flags; |
| { |
| regex_t regex = { 0 }; |
| regmatch_t *matches; |
| int rflags; |
| #if defined (ARRAY_VARS) |
| SHELL_VAR *rematch; |
| ARRAY *amatch; |
| int subexp_ind; |
| char *subexp_str; |
| int subexp_len; |
| #endif |
| int result; |
| |
| #if defined (ARRAY_VARS) |
| rematch = (SHELL_VAR *)NULL; |
| #endif |
| |
| rflags = REG_EXTENDED; |
| if (glob_ignore_case || match_ignore_case) |
| rflags |= REG_ICASE; |
| #if !defined (ARRAY_VARS) |
| rflags |= REG_NOSUB; |
| #endif |
| |
| if (regcomp (®ex, pattern, rflags)) |
| return 2; /* flag for printing a warning here. */ |
| |
| #if defined (ARRAY_VARS) |
| matches = (regmatch_t *)malloc (sizeof (regmatch_t) * (regex.re_nsub + 1)); |
| #else |
| matches = NULL; |
| #endif |
| |
| if (regexec (®ex, string, regex.re_nsub + 1, matches, 0)) |
| result = EXECUTION_FAILURE; |
| else |
| result = EXECUTION_SUCCESS; /* match */ |
| |
| #if defined (ARRAY_VARS) |
| subexp_len = strlen (string) + 10; |
| subexp_str = malloc (subexp_len + 1); |
| |
| /* Store the parenthesized subexpressions in the array BASH_REMATCH. |
| Element 0 is the portion that matched the entire regexp. Element 1 |
| is the part that matched the first subexpression, and so on. */ |
| unbind_variable ("BASH_REMATCH"); |
| rematch = make_new_array_variable ("BASH_REMATCH"); |
| amatch = array_cell (rematch); |
| |
| if ((flags & SHMAT_SUBEXP) && result == EXECUTION_SUCCESS && subexp_str) |
| { |
| for (subexp_ind = 0; subexp_ind <= regex.re_nsub; subexp_ind++) |
| { |
| memset (subexp_str, 0, subexp_len); |
| strncpy (subexp_str, string + matches[subexp_ind].rm_so, |
| matches[subexp_ind].rm_eo - matches[subexp_ind].rm_so); |
| array_insert (amatch, subexp_ind, subexp_str); |
| } |
| } |
| |
| VSETATTR (rematch, att_readonly); |
| |
| free (subexp_str); |
| free (matches); |
| #endif /* ARRAY_VARS */ |
| |
| regfree (®ex); |
| |
| return result; |
| } |
| |
| #endif /* HAVE_POSIX_REGEXP */ |