blob: d7315e388bbeedaf8d430433855c6f23002b6bda [file] [log] [blame]
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001/* pathexp.c -- The shell interface to the globbing library. */
2
Chet Rameyac50fba2014-02-26 09:36:43 -05003/* Copyright (C) 1995-2014 Free Software Foundation, Inc.
Jari Aaltoccc6cda1996-12-23 17:02:34 +00004
5 This file is part of GNU Bash, the Bourne Again SHell.
6
Jari Aalto31859422009-01-12 13:36:28 +00007 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
Jari Aaltoccc6cda1996-12-23 17:02:34 +000011
Jari Aalto31859422009-01-12 13:36:28 +000012 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
Jari Aaltoccc6cda1996-12-23 17:02:34 +000016
Jari Aalto31859422009-01-12 13:36:28 +000017 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19*/
Jari Aaltoccc6cda1996-12-23 17:02:34 +000020
21#include "config.h"
22
23#include "bashtypes.h"
24#include <stdio.h>
25
26#if defined (HAVE_UNISTD_H)
27# include <unistd.h>
28#endif
29
30#include "bashansi.h"
31
32#include "shell.h"
33#include "pathexp.h"
34#include "flags.h"
35
Jari Aalto7117c2d2002-07-17 14:10:11 +000036#include "shmbutil.h"
Jari Aalto31859422009-01-12 13:36:28 +000037#include "bashintl.h"
Jari Aalto7117c2d2002-07-17 14:10:11 +000038
Jari Aaltof73dda02001-11-13 17:56:06 +000039#include <glob/strmatch.h>
Jari Aaltob72432f1999-02-19 17:11:39 +000040
Jari Aalto7117c2d2002-07-17 14:10:11 +000041static int glob_name_is_acceptable __P((const char *));
42static void ignore_globbed_names __P((char **, sh_ignore_func_t *));
Chet Ramey495aee42011-11-22 19:11:26 -050043static char *split_ignorespec __P((char *, int *));
Chet Rameyac50fba2014-02-26 09:36:43 -050044
Jari Aaltob72432f1999-02-19 17:11:39 +000045#if defined (USE_POSIX_GLOB_LIBRARY)
46# include <glob.h>
Jari Aaltof73dda02001-11-13 17:56:06 +000047typedef int posix_glob_errfunc_t __P((const char *, int));
Jari Aaltob72432f1999-02-19 17:11:39 +000048#else
49# include <glob/glob.h>
50#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000051
52/* Control whether * matches .files in globbing. */
53int glob_dot_filenames;
54
Jari Aaltocce855b1998-04-17 19:52:44 +000055/* Control whether the extended globbing features are enabled. */
Chet Ramey00018032011-11-21 20:51:19 -050056int extended_glob = EXTGLOB_DEFAULT;
Jari Aaltocce855b1998-04-17 19:52:44 +000057
Jari Aalto31859422009-01-12 13:36:28 +000058/* Control enabling special handling of `**' */
59int glob_star = 0;
60
Jari Aaltoccc6cda1996-12-23 17:02:34 +000061/* Return nonzero if STRING has any unquoted special globbing chars in it. */
62int
63unquoted_glob_pattern_p (string)
64 register char *string;
65{
66 register int c;
Jari Aalto7117c2d2002-07-17 14:10:11 +000067 char *send;
Jari Aaltoccc6cda1996-12-23 17:02:34 +000068 int open;
69
Jari Aalto7117c2d2002-07-17 14:10:11 +000070 DECLARE_MBSTATE;
71
Jari Aaltoccc6cda1996-12-23 17:02:34 +000072 open = 0;
Jari Aalto7117c2d2002-07-17 14:10:11 +000073 send = string + strlen (string);
74
Jari Aaltoccc6cda1996-12-23 17:02:34 +000075 while (c = *string++)
76 {
77 switch (c)
78 {
79 case '?':
80 case '*':
81 return (1);
82
83 case '[':
84 open++;
85 continue;
86
87 case ']':
88 if (open)
89 return (1);
90 continue;
91
Jari Aaltocce855b1998-04-17 19:52:44 +000092 case '+':
93 case '@':
94 case '!':
95 if (*string == '(') /*)*/
96 return (1);
97 continue;
98
Jari Aaltoccc6cda1996-12-23 17:02:34 +000099 case CTLESC:
100 case '\\':
101 if (*string++ == '\0')
102 return (0);
103 }
Jari Aalto7117c2d2002-07-17 14:10:11 +0000104
105 /* Advance one fewer byte than an entire multibyte character to
106 account for the auto-increment in the loop above. */
107#ifdef HANDLE_MULTIBYTE
108 string--;
109 ADVANCE_CHAR_P (string, send - string);
110 string++;
111#else
112 ADVANCE_CHAR_P (string, send - string);
113#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000114 }
115 return (0);
116}
117
Jari Aaltof1be6662008-11-18 13:15:12 +0000118/* Return 1 if C is a character that is `special' in a POSIX ERE and needs to
119 be quoted to match itself. */
120static inline int
121ere_char (c)
122 int c;
123{
124 switch (c)
125 {
126 case '.':
127 case '[':
128 case '\\':
129 case '(':
130 case ')':
131 case '*':
132 case '+':
133 case '?':
134 case '{':
135 case '|':
136 case '^':
137 case '$':
138 return 1;
139 default:
140 return 0;
141 }
142 return (0);
143}
144
Jari Aalto31859422009-01-12 13:36:28 +0000145int
146glob_char_p (s)
147 const char *s;
148{
149 switch (*s)
150 {
151 case '*':
152 case '[':
153 case ']':
154 case '?':
155 case '\\':
156 return 1;
157 case '+':
158 case '@':
159 case '!':
Chet Rameyac50fba2014-02-26 09:36:43 -0500160 if (s[1] == '(') /*(*/
Jari Aalto31859422009-01-12 13:36:28 +0000161 return 1;
162 break;
163 }
164 return 0;
165}
166
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000167/* PATHNAME can contain characters prefixed by CTLESC; this indicates
168 that the character is to be quoted. We quote it here in the style
Jari Aaltocce855b1998-04-17 19:52:44 +0000169 that the glob library recognizes. If flags includes QGLOB_CVTNULL,
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000170 we change quoted null strings (pathname[0] == CTLNUL) into empty
171 strings (pathname[0] == 0). If this is called after quote removal
Jari Aaltocce855b1998-04-17 19:52:44 +0000172 is performed, (flags & QGLOB_CVTNULL) should be 0; if called when quote
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000173 removal has not been done (for example, before attempting to match a
Jari Aaltocce855b1998-04-17 19:52:44 +0000174 pattern while executing a case statement), flags should include
175 QGLOB_CVTNULL. If flags includes QGLOB_FILENAME, appropriate quoting
Chet Rameyac50fba2014-02-26 09:36:43 -0500176 to match a filename should be performed. QGLOB_REGEXP means we're
177 quoting for a Posix ERE (for [[ string =~ pat ]]) and that requires
178 some special handling. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000179char *
Jari Aaltocce855b1998-04-17 19:52:44 +0000180quote_string_for_globbing (pathname, qflags)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000181 const char *pathname;
Jari Aaltocce855b1998-04-17 19:52:44 +0000182 int qflags;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000183{
184 char *temp;
Jari Aaltocce855b1998-04-17 19:52:44 +0000185 register int i, j;
Chet Rameyac50fba2014-02-26 09:36:43 -0500186 int brack, cclass, collsym, equiv, c, last_was_backslash;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000187
Chet Rameyac50fba2014-02-26 09:36:43 -0500188 temp = (char *)xmalloc (2 * strlen (pathname) + 1);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000189
Jari Aaltocce855b1998-04-17 19:52:44 +0000190 if ((qflags & QGLOB_CVTNULL) && QUOTED_NULL (pathname))
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000191 {
192 temp[0] = '\0';
193 return temp;
194 }
195
Chet Rameyac50fba2014-02-26 09:36:43 -0500196 brack = cclass = collsym = equiv = last_was_backslash = 0;
Jari Aaltocce855b1998-04-17 19:52:44 +0000197 for (i = j = 0; pathname[i]; i++)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000198 {
Chet Rameyac50fba2014-02-26 09:36:43 -0500199 /* Fix for CTLESC at the end of the string? */
200 if (pathname[i] == CTLESC && pathname[i+1] == '\0')
201 {
202 temp[j++] = pathname[i++];
203 break;
204 }
205 /* If we are parsing regexp, turn CTLESC CTLESC into CTLESC. It's not an
206 ERE special character, so we should just be able to pass it through. */
207 else if ((qflags & QGLOB_REGEXP) && pathname[i] == CTLESC && pathname[i+1] == CTLESC)
208 {
209 i++;
210 temp[j++] = pathname[i];
211 continue;
212 }
213 else if (pathname[i] == CTLESC)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000214 {
215 if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
216 continue;
Chet Rameyac50fba2014-02-26 09:36:43 -0500217 /* What to do if preceding char is backslash? */
Chet Ramey25db9a72011-11-22 20:02:46 -0500218 if (pathname[i+1] != CTLESC && (qflags & QGLOB_REGEXP) && ere_char (pathname[i+1]) == 0)
Jari Aaltof1be6662008-11-18 13:15:12 +0000219 continue;
Jari Aaltocce855b1998-04-17 19:52:44 +0000220 temp[j++] = '\\';
Jari Aalto7117c2d2002-07-17 14:10:11 +0000221 i++;
222 if (pathname[i] == '\0')
223 break;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000224 }
Chet Rameyac50fba2014-02-26 09:36:43 -0500225 else if ((qflags & QGLOB_REGEXP) && (i == 0 || pathname[i-1] != CTLESC) && pathname[i] == '[') /*]*/
Jari Aalto31859422009-01-12 13:36:28 +0000226 {
Chet Rameyac50fba2014-02-26 09:36:43 -0500227 brack = 1;
228 temp[j++] = pathname[i++]; /* open bracket */
229 c = pathname[i++]; /* c == char after open bracket */
230 do
231 {
232 if (c == 0)
233 goto endpat;
234 else if (c == CTLESC)
235 {
236 /* skip c, check for EOS, let assignment at end of loop */
237 /* pathname[i] == backslash-escaped character */
238 if (pathname[i] == 0)
239 goto endpat;
240 temp[j++] = pathname[i++];
241 }
242 else if (c == '[' && pathname[i] == ':')
243 {
244 temp[j++] = c;
245 temp[j++] = pathname[i++];
246 cclass = 1;
247 }
248 else if (cclass && c == ':' && pathname[i] == ']')
249 {
250 temp[j++] = c;
251 temp[j++] = pathname[i++];
252 cclass = 0;
253 }
254 else if (c == '[' && pathname[i] == '=')
255 {
256 temp[j++] = c;
257 temp[j++] = pathname[i++];
258 if (pathname[i] == ']')
259 temp[j++] = pathname[i++]; /* right brack can be in equiv */
260 equiv = 1;
261 }
262 else if (equiv && c == '=' && pathname[i] == ']')
263 {
264 temp[j++] = c;
265 temp[j++] = pathname[i++];
266 equiv = 0;
267 }
268 else if (c == '[' && pathname[i] == '.')
269 {
270 temp[j++] = c;
271 temp[j++] = pathname[i++];
272 if (pathname[i] == ']')
273 temp[j++] = pathname[i++]; /* right brack can be in collsym */
274 collsym = 1;
275 }
276 else if (collsym && c == '.' && pathname[i] == ']')
277 {
278 temp[j++] = c;
279 temp[j++] = pathname[i++];
280 collsym = 0;
281 }
282 else
283 temp[j++] = c;
284 }
285 while ((c = pathname[i++]) != ']');
286 temp[j++] = c; /* closing right bracket */
287 i--; /* increment will happen above in loop */
288 continue; /* skip double assignment below */
289 }
290 else if (pathname[i] == '\\' && (qflags & QGLOB_REGEXP) == 0)
291 {
292 /* XXX - if not quoting regexp, use backslash as quote char. Should
293 we just pass it through without treating it as special? That is
294 what ksh93 seems to do. */
295
296 /* If we want to pass through backslash unaltered, comment out these
297 lines. */
Jari Aalto31859422009-01-12 13:36:28 +0000298 temp[j++] = '\\';
Chet Rameyac50fba2014-02-26 09:36:43 -0500299
Jari Aalto31859422009-01-12 13:36:28 +0000300 i++;
301 if (pathname[i] == '\0')
302 break;
303 }
Chet Rameyac50fba2014-02-26 09:36:43 -0500304 else if (pathname[i] == '\\' && (qflags & QGLOB_REGEXP))
305 last_was_backslash = 1;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000306 temp[j++] = pathname[i];
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000307 }
Chet Rameyac50fba2014-02-26 09:36:43 -0500308endpat:
Jari Aaltocce855b1998-04-17 19:52:44 +0000309 temp[j] = '\0';
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000310
311 return (temp);
312}
313
314char *
315quote_globbing_chars (string)
316 char *string;
317{
Jari Aalto7117c2d2002-07-17 14:10:11 +0000318 size_t slen;
319 char *temp, *s, *t, *send;
320 DECLARE_MBSTATE;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000321
Jari Aalto7117c2d2002-07-17 14:10:11 +0000322 slen = strlen (string);
323 send = string + slen;
324
325 temp = (char *)xmalloc (slen * 2 + 1);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000326 for (t = temp, s = string; *s; )
327 {
Jari Aalto31859422009-01-12 13:36:28 +0000328 if (glob_char_p (s))
329 *t++ = '\\';
Jari Aalto7117c2d2002-07-17 14:10:11 +0000330
331 /* Copy a single (possibly multibyte) character from s to t,
Chet Rameyac50fba2014-02-26 09:36:43 -0500332 incrementing both. */
Jari Aalto7117c2d2002-07-17 14:10:11 +0000333 COPY_CHAR_P (t, s, send);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000334 }
335 *t = '\0';
336 return temp;
337}
338
339/* Call the glob library to do globbing on PATHNAME. */
340char **
341shell_glob_filename (pathname)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000342 const char *pathname;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000343{
344#if defined (USE_POSIX_GLOB_LIBRARY)
345 register int i;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000346 char *temp, **results;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000347 glob_t filenames;
348 int glob_flags;
349
Jari Aaltocce855b1998-04-17 19:52:44 +0000350 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000351
352 filenames.gl_offs = 0;
353
Jari Aaltob72432f1999-02-19 17:11:39 +0000354# if defined (GLOB_PERIOD)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000355 glob_flags = glob_dot_filenames ? GLOB_PERIOD : 0;
Jari Aaltob72432f1999-02-19 17:11:39 +0000356# else
357 glob_flags = 0;
358# endif /* !GLOB_PERIOD */
359
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000360 glob_flags |= (GLOB_ERR | GLOB_DOOFFS);
361
Jari Aaltof73dda02001-11-13 17:56:06 +0000362 i = glob (temp, glob_flags, (posix_glob_errfunc_t *)NULL, &filenames);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000363
364 free (temp);
365
Jari Aalto28ef6c32001-04-06 19:14:31 +0000366 if (i == GLOB_NOSPACE || i == GLOB_ABORTED)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000367 return ((char **)NULL);
Jari Aaltob72432f1999-02-19 17:11:39 +0000368 else if (i == GLOB_NOMATCH)
369 filenames.gl_pathv = (char **)NULL;
370 else if (i != 0) /* other error codes not in POSIX.2 */
Jari Aaltocce855b1998-04-17 19:52:44 +0000371 filenames.gl_pathv = (char **)NULL;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000372
Jari Aaltobb706242000-03-17 21:46:59 +0000373 results = filenames.gl_pathv;
374
375 if (results && ((GLOB_FAILED (results)) == 0))
376 {
377 if (should_ignore_glob_matches ())
378 ignore_glob_matches (results);
379 if (results && results[0])
Jari Aalto7117c2d2002-07-17 14:10:11 +0000380 strvec_sort (results);
Jari Aaltobb706242000-03-17 21:46:59 +0000381 else
382 {
383 FREE (results);
384 results = (char **)NULL;
385 }
386 }
387
388 return (results);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000389
390#else /* !USE_POSIX_GLOB_LIBRARY */
391
392 char *temp, **results;
393
394 noglob_dot_filenames = glob_dot_filenames == 0;
395
Jari Aaltocce855b1998-04-17 19:52:44 +0000396 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
Jari Aalto31859422009-01-12 13:36:28 +0000397 results = glob_filename (temp, glob_star ? GX_GLOBSTAR : 0);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000398 free (temp);
399
400 if (results && ((GLOB_FAILED (results)) == 0))
401 {
402 if (should_ignore_glob_matches ())
403 ignore_glob_matches (results);
404 if (results && results[0])
Jari Aalto7117c2d2002-07-17 14:10:11 +0000405 strvec_sort (results);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000406 else
407 {
408 FREE (results);
409 results = (char **)&glob_error_return;
410 }
411 }
412
413 return (results);
414#endif /* !USE_POSIX_GLOB_LIBRARY */
415}
416
417/* Stuff for GLOBIGNORE. */
418
419static struct ignorevar globignore =
420{
421 "GLOBIGNORE",
422 (struct ign *)0,
423 0,
424 (char *)0,
Jari Aaltof73dda02001-11-13 17:56:06 +0000425 (sh_iv_item_func_t *)0,
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000426};
427
428/* Set up to ignore some glob matches because the value of GLOBIGNORE
429 has changed. If GLOBIGNORE is being unset, we also need to disable
430 the globbing of filenames beginning with a `.'. */
431void
432setup_glob_ignore (name)
433 char *name;
434{
435 char *v;
436
437 v = get_string_value (name);
438 setup_ignore_patterns (&globignore);
439
440 if (globignore.num_ignores)
441 glob_dot_filenames = 1;
442 else if (v == 0)
443 glob_dot_filenames = 0;
444}
445
446int
447should_ignore_glob_matches ()
448{
449 return globignore.num_ignores;
450}
451
452/* Return 0 if NAME matches a pattern in the globignore.ignores list. */
453static int
454glob_name_is_acceptable (name)
Jari Aaltof73dda02001-11-13 17:56:06 +0000455 const char *name;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000456{
457 struct ign *p;
Jari Aaltocce855b1998-04-17 19:52:44 +0000458 int flags;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000459
460 /* . and .. are never matched */
461 if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
462 return (0);
463
Jari Aaltocce855b1998-04-17 19:52:44 +0000464 flags = FNM_PATHNAME | FNMATCH_EXTFLAG;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000465 for (p = globignore.ignores; p->val; p++)
466 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000467 if (strmatch (p->val, (char *)name, flags) != FNM_NOMATCH)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000468 return (0);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000469 }
470 return (1);
471}
472
473/* Internal function to test whether filenames in NAMES should be
474 ignored. NAME_FUNC is a pointer to a function to call with each
475 name. It returns non-zero if the name is acceptable to the particular
476 ignore function which called _ignore_names; zero if the name should
477 be removed from NAMES. */
478
479static void
480ignore_globbed_names (names, name_func)
481 char **names;
Jari Aaltof73dda02001-11-13 17:56:06 +0000482 sh_ignore_func_t *name_func;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000483{
484 char **newnames;
485 int n, i;
486
487 for (i = 0; names[i]; i++)
488 ;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000489 newnames = strvec_create (i + 1);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000490
491 for (n = i = 0; names[i]; i++)
492 {
493 if ((*name_func) (names[i]))
Jari Aalto28ef6c32001-04-06 19:14:31 +0000494 newnames[n++] = names[i];
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000495 else
496 free (names[i]);
497 }
498
499 newnames[n] = (char *)NULL;
500
501 if (n == 0)
502 {
503 names[0] = (char *)NULL;
504 free (newnames);
505 return;
506 }
507
508 /* Copy the acceptable names from NEWNAMES back to NAMES and set the
509 new array end. */
510 for (n = 0; newnames[n]; n++)
511 names[n] = newnames[n];
512 names[n] = (char *)NULL;
Jari Aaltod166f041997-06-05 14:59:13 +0000513 free (newnames);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000514}
515
516void
517ignore_glob_matches (names)
518 char **names;
519{
520 if (globignore.num_ignores == 0)
521 return;
522
523 ignore_globbed_names (names, glob_name_is_acceptable);
524}
525
Chet Ramey495aee42011-11-22 19:11:26 -0500526static char *
527split_ignorespec (s, ip)
528 char *s;
529 int *ip;
530{
531 char *t;
532 int n, i;
533
534 if (s == 0)
535 return 0;
536
537 i = *ip;
538 if (s[i] == 0)
539 return 0;
540
541 n = skip_to_delim (s, i, ":", SD_NOJMP|SD_EXTGLOB);
542 t = substring (s, i, n);
543
544 if (s[n] == ':')
545 n++;
546 *ip = n;
547 return t;
548}
549
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000550void
551setup_ignore_patterns (ivp)
552 struct ignorevar *ivp;
553{
554 int numitems, maxitems, ptr;
555 char *colon_bit, *this_ignoreval;
556 struct ign *p;
557
558 this_ignoreval = get_string_value (ivp->varname);
559
560 /* If nothing has changed then just exit now. */
561 if ((this_ignoreval && ivp->last_ignoreval && STREQ (this_ignoreval, ivp->last_ignoreval)) ||
562 (!this_ignoreval && !ivp->last_ignoreval))
563 return;
564
565 /* Oops. The ignore variable has changed. Re-parse it. */
566 ivp->num_ignores = 0;
567
568 if (ivp->ignores)
569 {
570 for (p = ivp->ignores; p->val; p++)
571 free(p->val);
572 free (ivp->ignores);
573 ivp->ignores = (struct ign *)NULL;
574 }
575
576 if (ivp->last_ignoreval)
577 {
578 free (ivp->last_ignoreval);
579 ivp->last_ignoreval = (char *)NULL;
580 }
581
582 if (this_ignoreval == 0 || *this_ignoreval == '\0')
583 return;
584
585 ivp->last_ignoreval = savestring (this_ignoreval);
586
587 numitems = maxitems = ptr = 0;
588
Chet Ramey495aee42011-11-22 19:11:26 -0500589#if 0
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000590 while (colon_bit = extract_colon_unit (this_ignoreval, &ptr))
Chet Ramey495aee42011-11-22 19:11:26 -0500591#else
592 while (colon_bit = split_ignorespec (this_ignoreval, &ptr))
593#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000594 {
595 if (numitems + 1 >= maxitems)
596 {
597 maxitems += 10;
598 ivp->ignores = (struct ign *)xrealloc (ivp->ignores, maxitems * sizeof (struct ign));
599 }
600 ivp->ignores[numitems].val = colon_bit;
601 ivp->ignores[numitems].len = strlen (colon_bit);
602 ivp->ignores[numitems].flags = 0;
603 if (ivp->item_func)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000604 (*ivp->item_func) (&ivp->ignores[numitems]);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000605 numitems++;
606 }
607 ivp->ignores[numitems].val = (char *)NULL;
608 ivp->num_ignores = numitems;
609}