Line data Source code
1 : /* 2 : * shmatch.c -- shell interface to posix regular expression matching. 3 : */ 4 : 5 : /* Copyright (C) 2003-2015 Free Software Foundation, Inc. 6 : 7 : This file is part of GNU Bash, the Bourne Again SHell. 8 : 9 : Bash is free software: you can redistribute it and/or modify 10 : it under the terms of the GNU General Public License as published by 11 : the Free Software Foundation, either version 3 of the License, or 12 : (at your option) any later version. 13 : 14 : Bash is distributed in the hope that it will be useful, 15 : but WITHOUT ANY WARRANTY; without even the implied warranty of 16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 : GNU General Public License for more details. 18 : 19 : You should have received a copy of the GNU General Public License 20 : along with Bash. If not, see <http://www.gnu.org/licenses/>. 21 : */ 22 : 23 : #ifdef HAVE_CONFIG_H 24 : # include <config.h> 25 : #endif 26 : 27 : #if defined (HAVE_POSIX_REGEXP) 28 : 29 : #ifdef HAVE_UNISTD_H 30 : # include <unistd.h> 31 : #endif 32 : 33 : #include "bashansi.h" 34 : 35 : #include <stdio.h> 36 : #include <regex.h> 37 : 38 : #include "shell.h" 39 : #include "variables.h" 40 : #include "externs.h" 41 : 42 : extern int glob_ignore_case, match_ignore_case; 43 : 44 : int 45 0 : sh_regmatch (string, pattern, flags) 46 : const char *string; 47 : const char *pattern; 48 : int flags; 49 : { 50 0 : regex_t regex = { 0 }; 51 0 : regmatch_t *matches; 52 0 : int rflags; 53 : #if defined (ARRAY_VARS) 54 0 : SHELL_VAR *rematch; 55 0 : ARRAY *amatch; 56 0 : int subexp_ind; 57 0 : char *subexp_str; 58 0 : int subexp_len; 59 : #endif 60 0 : int result; 61 : 62 : #if defined (ARRAY_VARS) 63 0 : rematch = (SHELL_VAR *)NULL; 64 : #endif 65 : 66 0 : rflags = REG_EXTENDED; 67 0 : if (glob_ignore_case || match_ignore_case) 68 0 : rflags |= REG_ICASE; 69 : #if !defined (ARRAY_VARS) 70 : rflags |= REG_NOSUB; 71 : #endif 72 : 73 0 : if (regcomp (®ex, pattern, rflags)) 74 : return 2; /* flag for printing a warning here. */ 75 : 76 : #if defined (ARRAY_VARS) 77 0 : matches = (regmatch_t *)malloc (sizeof (regmatch_t) * (regex.re_nsub + 1)); 78 : #else 79 : matches = NULL; 80 : #endif 81 : 82 : /* man regexec: NULL PMATCH ignored if NMATCH == 0 */ 83 0 : if (regexec (®ex, string, matches ? regex.re_nsub + 1 : 0, matches, 0)) 84 : result = EXECUTION_FAILURE; 85 : else 86 0 : result = EXECUTION_SUCCESS; /* match */ 87 : 88 : #if defined (ARRAY_VARS) 89 0 : subexp_len = strlen (string) + 10; 90 0 : subexp_str = malloc (subexp_len + 1); 91 : 92 : /* Store the parenthesized subexpressions in the array BASH_REMATCH. 93 : Element 0 is the portion that matched the entire regexp. Element 1 94 : is the part that matched the first subexpression, and so on. */ 95 0 : unbind_variable_noref ("BASH_REMATCH"); 96 0 : rematch = make_new_array_variable ("BASH_REMATCH"); 97 0 : amatch = array_cell (rematch); 98 : 99 0 : if (matches && (flags & SHMAT_SUBEXP) && result == EXECUTION_SUCCESS && subexp_str) 100 : { 101 0 : for (subexp_ind = 0; subexp_ind <= regex.re_nsub; subexp_ind++) 102 : { 103 0 : memset (subexp_str, 0, subexp_len); 104 0 : strncpy (subexp_str, string + matches[subexp_ind].rm_so, 105 0 : matches[subexp_ind].rm_eo - matches[subexp_ind].rm_so); 106 0 : array_insert (amatch, subexp_ind, subexp_str); 107 : } 108 : } 109 : 110 0 : VSETATTR (rematch, att_readonly); 111 : 112 0 : free (subexp_str); 113 0 : free (matches); 114 : #endif /* ARRAY_VARS */ 115 : 116 0 : regfree (®ex); 117 : 118 0 : return result; 119 : } 120 : 121 : #endif /* HAVE_POSIX_REGEXP */