Print this page
make: use the more modern wchar routines, not widec.h
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/make/bin/files.cc
+++ new/usr/src/cmd/make/bin/files.cc
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 /*
27 27 * files.c
28 28 *
29 29 * Various file related routines:
30 30 * Figure out if file exists
31 31 * Wildcard resolution for directory reader
32 32 * Directory reader
33 33 */
34 34
35 35
36 36 /*
37 37 * Included files
38 38 */
39 39 #include <dirent.h> /* opendir() */
40 40 #include <errno.h> /* errno */
41 41 #include <mk/defs.h>
42 42 #include <mksh/macro.h> /* getvar() */
43 43 #include <mksh/misc.h> /* get_prop(), append_prop() */
44 44 #include <sys/stat.h> /* lstat() */
45 45 #include <libintl.h>
46 46
47 47 /*
48 48 * Defined macros
49 49 */
50 50
51 51 /*
52 52 * typedefs & structs
53 53 */
54 54
55 55 /*
56 56 * Static variables
57 57 */
58 58
59 59 /*
60 60 * File table of contents
61 61 */
62 62 extern timestruc_t& exists(register Name target);
63 63 extern void set_target_stat(register Name target, struct stat buf);
64 64 static timestruc_t& vpath_exists(register Name target);
65 65 static Name enter_file_name(wchar_t *name_string, wchar_t *library);
66 66 static Boolean star_match(register char *string, register char *pattern);
67 67 static Boolean amatch(register wchar_t *string, register wchar_t *pattern);
68 68
69 69 /*
70 70 * exists(target)
71 71 *
72 72 * Figure out the timestamp for one target.
73 73 *
74 74 * Return value:
75 75 * The time the target was created
76 76 *
77 77 * Parameters:
78 78 * target The target to check
79 79 *
80 80 * Global variables used:
81 81 * debug_level Should we trace the stat call?
82 82 * recursion_level Used for tracing
83 83 * vpath_defined Was the variable VPATH defined in environment?
84 84 */
85 85 timestruc_t&
86 86 exists(register Name target)
87 87 {
88 88 struct stat buf;
89 89 register int result;
90 90
91 91 /* We cache stat information. */
92 92 if (target->stat.time != file_no_time) {
93 93 return target->stat.time;
94 94 }
95 95
96 96 /*
97 97 * If the target is a member, we have to extract the time
98 98 * from the archive.
99 99 */
100 100 if (target->is_member &&
101 101 (get_prop(target->prop, member_prop) != NULL)) {
102 102 return read_archive(target);
103 103 }
104 104
105 105 if (debug_level > 1) {
106 106 (void) printf("%*sstat(%s)\n",
107 107 recursion_level,
108 108 "",
109 109 target->string_mb);
110 110 }
111 111
112 112 result = lstat_vroot(target->string_mb, &buf, NULL, VROOT_DEFAULT);
113 113 if ((result != -1) && ((buf.st_mode & S_IFMT) == S_IFLNK)) {
114 114 /*
115 115 * If the file is a symbolic link, we remember that
116 116 * and then we get the status for the refd file.
117 117 */
118 118 target->stat.is_sym_link = true;
119 119 result = stat_vroot(target->string_mb, &buf, NULL, VROOT_DEFAULT);
120 120 } else {
121 121 target->stat.is_sym_link = false;
122 122 }
123 123
124 124 if (result < 0) {
125 125 target->stat.time = file_doesnt_exist;
126 126 target->stat.stat_errno = errno;
127 127 if ((errno == ENOENT) &&
128 128 vpath_defined &&
129 129 /* azv, fixing bug 1262942, VPATH works with a leaf name
130 130 * but not a directory name.
131 131 */
132 132 (target->string_mb[0] != (int) slash_char) ) {
133 133 /* BID_1214655 */
134 134 /* azv */
135 135 vpath_exists(target);
136 136 // return vpath_exists(target);
137 137 }
138 138 } else {
139 139 /* Save all the information we need about the file */
140 140 target->stat.stat_errno = 0;
141 141 target->stat.is_file = true;
142 142 target->stat.mode = buf.st_mode & 0777;
143 143 target->stat.size = buf.st_size;
144 144 target->stat.is_dir =
145 145 BOOLEAN((buf.st_mode & S_IFMT) == S_IFDIR);
146 146 if (target->stat.is_dir) {
147 147 target->stat.time = file_is_dir;
148 148 } else {
149 149 /* target->stat.time = buf.st_mtime; */
150 150 /* BID_1129806 */
151 151 /* vis@nbsp.nsk.su */
152 152 target->stat.time = MAX(buf.st_mtim, file_min_time);
153 153 }
154 154 }
155 155 if ((target->colon_splits > 0) &&
156 156 (get_prop(target->prop, time_prop) == NULL)) {
157 157 append_prop(target, time_prop)->body.time.time =
158 158 target->stat.time;
159 159 }
160 160 return target->stat.time;
161 161 }
162 162
163 163 /*
164 164 * set_target_stat( target, buf)
165 165 *
166 166 * Called by exists() to set some stat fields in the Name structure
167 167 * to those read by the stat_vroot() call (from disk).
168 168 *
169 169 * Parameters:
170 170 * target The target whose stat field is set
171 171 * buf stat values (on disk) of the file
172 172 * represented by target.
173 173 */
174 174 void
175 175 set_target_stat(register Name target, struct stat buf)
176 176 {
177 177 target->stat.stat_errno = 0;
178 178 target->stat.is_file = true;
179 179 target->stat.mode = buf.st_mode & 0777;
180 180 target->stat.size = buf.st_size;
181 181 target->stat.is_dir =
182 182 BOOLEAN((buf.st_mode & S_IFMT) == S_IFDIR);
183 183 if (target->stat.is_dir) {
184 184 target->stat.time = file_is_dir;
185 185 } else {
186 186 /* target->stat.time = buf.st_mtime; */
187 187 /* BID_1129806 */
188 188 /* vis@nbsp.nsk.su */
189 189 target->stat.time = MAX(buf.st_mtim, file_min_time);
190 190 }
191 191 }
192 192
193 193
194 194 /*
195 195 * vpath_exists(target)
196 196 *
197 197 * Called if exists() discovers that there is a VPATH defined.
198 198 * This function stats the VPATH translation of the target.
199 199 *
200 200 * Return value:
201 201 * The time the target was created
202 202 *
203 203 * Parameters:
204 204 * target The target to check
205 205 *
206 206 * Global variables used:
207 207 * vpath_name The Name "VPATH", used to get macro value
208 208 */
209 209 static timestruc_t&
210 210 vpath_exists(register Name target)
211 211 {
212 212 wchar_t *vpath;
213 213 wchar_t file_name[MAXPATHLEN];
214 214 wchar_t *name_p;
215 215 Name alias;
216 216
217 217 /*
218 218 * To avoid recursive search through VPATH when exists(alias) is called
219 219 */
220 220 vpath_defined = false;
221 221
222 222 Wstring wcb(getvar(vpath_name));
223 223 Wstring wcb1(target);
↓ open down ↓ |
223 lines elided |
↑ open up ↑ |
224 224
225 225 vpath = wcb.get_string();
226 226
227 227 while (*vpath != (int) nul_char) {
228 228 name_p = file_name;
229 229 while ((*vpath != (int) colon_char) &&
230 230 (*vpath != (int) nul_char)) {
231 231 *name_p++ = *vpath++;
232 232 }
233 233 *name_p++ = (int) slash_char;
234 - (void) wscpy(name_p, wcb1.get_string());
234 + (void) wcscpy(name_p, wcb1.get_string());
235 235 alias = GETNAME(file_name, FIND_LENGTH);
236 236 if (exists(alias) != file_doesnt_exist) {
237 237 target->stat.is_file = true;
238 238 target->stat.mode = alias->stat.mode;
239 239 target->stat.size = alias->stat.size;
240 240 target->stat.is_dir = alias->stat.is_dir;
241 241 target->stat.time = alias->stat.time;
242 242 maybe_append_prop(target, vpath_alias_prop)->
243 243 body.vpath_alias.alias = alias;
244 244 target->has_vpath_alias_prop = true;
245 245 vpath_defined = true;
246 246 return alias->stat.time;
247 247 }
248 248 while ((*vpath != (int) nul_char) &&
249 249 ((*vpath == (int) colon_char) || iswspace(*vpath))) {
250 250 vpath++;
251 251 }
252 252 }
253 253 /*
254 254 * Restore vpath_defined
255 255 */
256 256 vpath_defined = true;
257 257 return target->stat.time;
258 258 }
259 259
260 260 /*
261 261 * read_dir(dir, pattern, line, library)
262 262 *
263 263 * Used to enter the contents of directories into makes namespace.
264 264 * Presence of a file is important when scanning for implicit rules.
265 265 * read_dir() is also used to expand wildcards in dependency lists.
266 266 *
267 267 * Return value:
268 268 * Non-0 if we found files to match the pattern
269 269 *
270 270 * Parameters:
271 271 * dir Path to the directory to read
272 272 * pattern Pattern for that files should match or NULL
273 273 * line When we scan using a pattern we enter files
274 274 * we find as dependencies for this line
275 275 * library If we scan for "lib.a(<wildcard-member>)"
276 276 *
277 277 * Global variables used:
278 278 * debug_level Should we trace the dir reading?
279 279 * dot The Name ".", compared against
280 280 * sccs_dir_path The path to the SCCS dir (from PROJECTDIR)
281 281 * vpath_defined Was the variable VPATH defined in environment?
282 282 * vpath_name The Name "VPATH", use to get macro value
283 283 */
284 284 int
285 285 read_dir(Name dir, wchar_t *pattern, Property line, wchar_t *library)
286 286 {
287 287 wchar_t file_name[MAXPATHLEN];
288 288 wchar_t *file_name_p = file_name;
289 289 Name file;
290 290 wchar_t plain_file_name[MAXPATHLEN];
291 291 wchar_t *plain_file_name_p;
292 292 Name plain_file;
293 293 wchar_t tmp_wcs_buffer[MAXPATHLEN];
294 294 DIR *dir_fd;
295 295 int m_local_dependency=0;
296 296 #define d_fileno d_ino
297 297 register struct dirent *dp;
298 298 wchar_t *vpath = NULL;
299 299 wchar_t *p;
300 300 int result = 0;
301 301
302 302 if(dir->hash.length >= MAXPATHLEN) {
303 303 return 0;
304 304 }
305 305
306 306 Wstring wcb(dir);
307 307 Wstring vps;
308 308
309 309 /* A directory is only read once unless we need to expand wildcards. */
310 310 if (pattern == NULL) {
311 311 if (dir->has_read_dir) {
312 312 return 0;
313 313 }
314 314 dir->has_read_dir = true;
315 315 }
316 316 /* Check if VPATH is active and setup list if it is. */
↓ open down ↓ |
72 lines elided |
↑ open up ↑ |
317 317 if (vpath_defined && (dir == dot)) {
318 318 vps.init(getvar(vpath_name));
319 319 vpath = vps.get_string();
320 320 }
321 321
322 322 /*
323 323 * Prepare the string where we build the full name of the
324 324 * files in the directory.
325 325 */
326 326 if ((dir->hash.length > 1) || (wcb.get_string()[0] != (int) period_char)) {
327 - (void) wscpy(file_name, wcb.get_string());
327 + (void) wcscpy(file_name, wcb.get_string());
328 328 MBSTOWCS(wcs_buffer, "/");
329 - (void) wscat(file_name, wcs_buffer);
330 - file_name_p = file_name + wslen(file_name);
329 + (void) wcscat(file_name, wcs_buffer);
330 + file_name_p = file_name + wcslen(file_name);
331 331 }
332 332
333 333 /* Open the directory. */
334 334 vpath_loop:
335 335 dir_fd = opendir(dir->string_mb);
336 336 if (dir_fd == NULL) {
337 337 return 0;
338 338 }
339 339
340 340 /* Read all the directory entries. */
341 341 while ((dp = readdir(dir_fd)) != NULL) {
342 342 /* We ignore "." and ".." */
343 343 if ((dp->d_fileno == 0) ||
344 344 ((dp->d_name[0] == (int) period_char) &&
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
345 345 ((dp->d_name[1] == 0) ||
346 346 ((dp->d_name[1] == (int) period_char) &&
347 347 (dp->d_name[2] == 0))))) {
348 348 continue;
349 349 }
350 350 /*
351 351 * Build the full name of the file using whatever
352 352 * path supplied to the function.
353 353 */
354 354 MBSTOWCS(tmp_wcs_buffer, dp->d_name);
355 - (void) wscpy(file_name_p, tmp_wcs_buffer);
355 + (void) wcscpy(file_name_p, tmp_wcs_buffer);
356 356 file = enter_file_name(file_name, library);
357 357 if ((pattern != NULL) && amatch(tmp_wcs_buffer, pattern)) {
358 358 /*
359 359 * If we are expanding a wildcard pattern, we
360 360 * enter the file as a dependency for the target.
361 361 */
362 362 if (debug_level > 0){
363 363 WCSTOMBS(mbs_buffer, pattern);
364 364 (void) printf(gettext("'%s: %s' due to %s expansion\n"),
365 365 line->body.line.target->string_mb,
366 366 file->string_mb,
367 367 mbs_buffer);
368 368 }
369 369 enter_dependency(line, file, false);
370 370 result++;
371 371 } else {
372 372 /*
373 373 * If the file has an SCCS/s. file,
374 374 * we will detect that later on.
375 375 */
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
376 376 file->stat.has_sccs = NO_SCCS;
377 377 /*
378 378 * If this is an s. file, we also enter it as if it
379 379 * existed in the plain directory.
380 380 */
381 381 if ((dp->d_name[0] == 's') &&
382 382 (dp->d_name[1] == (int) period_char)) {
383 383
384 384 MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2);
385 385 plain_file_name_p = plain_file_name;
386 - (void) wscpy(plain_file_name_p, tmp_wcs_buffer);
386 + (void) wcscpy(plain_file_name_p, tmp_wcs_buffer);
387 387 plain_file = GETNAME(plain_file_name, FIND_LENGTH);
388 388 plain_file->stat.is_file = true;
389 389 plain_file->stat.has_sccs = HAS_SCCS;
390 390 /*
391 391 * Enter the s. file as a dependency for the
392 392 * plain file.
393 393 */
394 394 maybe_append_prop(plain_file, sccs_prop)->
395 395 body.sccs.file = file;
396 396 MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2);
397 397 if ((pattern != NULL) &&
398 398 amatch(tmp_wcs_buffer, pattern)) {
399 399 if (debug_level > 0) {
400 400 WCSTOMBS(mbs_buffer, pattern);
401 401 (void) printf(gettext("'%s: %s' due to %s expansion\n"),
402 402 line->body.line.target->
403 403 string_mb,
404 404 plain_file->string_mb,
405 405 mbs_buffer);
406 406 }
407 407 enter_dependency(line, plain_file, false);
408 408 result++;
409 409 }
410 410 }
411 411 }
412 412 }
413 413 (void) closedir(dir_fd);
414 414 if ((vpath != NULL) && (*vpath != (int) nul_char)) {
415 415 while ((*vpath != (int) nul_char) &&
416 416 (iswspace(*vpath) || (*vpath == (int) colon_char))) {
417 417 vpath++;
418 418 }
419 419 p = vpath;
420 420 while ((*vpath != (int) colon_char) &&
421 421 (*vpath != (int) nul_char)) {
422 422 vpath++;
423 423 }
424 424 if (vpath > p) {
425 425 dir = GETNAME(p, vpath - p);
426 426 goto vpath_loop;
427 427 }
428 428 }
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
429 429 /*
430 430 * look into SCCS directory only if it's not svr4. For svr4 dont do that.
431 431 */
432 432
433 433 /*
434 434 * Now read the SCCS directory.
435 435 * Files in the SCSC directory are considered to be part of the set of
436 436 * files in the plain directory. They are also entered in their own right.
437 437 * Prepare the string where we build the true name of the SCCS files.
438 438 */
439 - (void) wsncpy(plain_file_name,
439 + (void) wcsncpy(plain_file_name,
440 440 file_name,
441 441 file_name_p - file_name);
442 442 plain_file_name[file_name_p - file_name] = 0;
443 - plain_file_name_p = plain_file_name + wslen(plain_file_name);
443 + plain_file_name_p = plain_file_name + wcslen(plain_file_name);
444 444
445 445 if(!svr4) {
446 446
447 447 if (sccs_dir_path != NULL) {
448 448 wchar_t tmp_wchar;
449 449 wchar_t path[MAXPATHLEN];
450 450 char mb_path[MAXPATHLEN];
451 451
452 452 if (file_name_p - file_name > 0) {
453 453 tmp_wchar = *file_name_p;
454 454 *file_name_p = 0;
455 455 WCSTOMBS(mbs_buffer, file_name);
456 456 (void) sprintf(mb_path, "%s/%s/SCCS",
457 457 sccs_dir_path,
458 458 mbs_buffer);
459 459 *file_name_p = tmp_wchar;
460 460 } else {
461 461 (void) sprintf(mb_path, "%s/SCCS", sccs_dir_path);
462 462 }
463 463 MBSTOWCS(path, mb_path);
464 - (void) wscpy(file_name, path);
464 + (void) wcscpy(file_name, path);
465 465 } else {
466 466 MBSTOWCS(wcs_buffer, "SCCS");
467 - (void) wscpy(file_name_p, wcs_buffer);
467 + (void) wcscpy(file_name_p, wcs_buffer);
468 468 }
469 469 } else {
470 470 MBSTOWCS(wcs_buffer, ".");
471 - (void) wscpy(file_name_p, wcs_buffer);
471 + (void) wcscpy(file_name_p, wcs_buffer);
472 472 }
473 473 /* Internalize the constructed SCCS dir name. */
474 474 (void) exists(dir = GETNAME(file_name, FIND_LENGTH));
475 475 /* Just give up if the directory file doesnt exist. */
476 476 if (!dir->stat.is_file) {
477 477 return result;
478 478 }
479 479 /* Open the directory. */
480 480 dir_fd = opendir(dir->string_mb);
481 481 if (dir_fd == NULL) {
482 482 return result;
483 483 }
484 484 MBSTOWCS(wcs_buffer, "/");
485 - (void) wscat(file_name, wcs_buffer);
486 - file_name_p = file_name + wslen(file_name);
485 + (void) wcscat(file_name, wcs_buffer);
486 + file_name_p = file_name + wcslen(file_name);
487 487
488 488 while ((dp = readdir(dir_fd)) != NULL) {
489 489 if ((dp->d_fileno == 0) ||
490 490 ((dp->d_name[0] == (int) period_char) &&
491 491 ((dp->d_name[1] == 0) ||
492 492 ((dp->d_name[1] == (int) period_char) &&
493 493 (dp->d_name[2] == 0))))) {
494 494 continue;
495 495 }
496 496 /* Construct and internalize the true name of the SCCS file. */
497 497 MBSTOWCS(wcs_buffer, dp->d_name);
498 - (void) wscpy(file_name_p, wcs_buffer);
498 + (void) wcscpy(file_name_p, wcs_buffer);
499 499 file = GETNAME(file_name, FIND_LENGTH);
500 500 file->stat.is_file = true;
501 501 file->stat.has_sccs = NO_SCCS;
502 502 /*
503 503 * If this is an s. file, we also enter it as if it
504 504 * existed in the plain directory.
505 505 */
506 506 if ((dp->d_name[0] == 's') &&
507 507 (dp->d_name[1] == (int) period_char)) {
508 508
509 509 MBSTOWCS(wcs_buffer, dp->d_name + 2);
510 - (void) wscpy(plain_file_name_p, wcs_buffer);
510 + (void) wcscpy(plain_file_name_p, wcs_buffer);
511 511 plain_file = GETNAME(plain_file_name, FIND_LENGTH);
512 512 plain_file->stat.is_file = true;
513 513 plain_file->stat.has_sccs = HAS_SCCS;
514 514 /* if sccs dependency is already set,skip */
515 515 if(plain_file->prop) {
516 516 Property sprop = get_prop(plain_file->prop,sccs_prop);
517 517 if(sprop != NULL) {
518 518 if (sprop->body.sccs.file) {
519 519 goto try_pattern;
520 520 }
521 521 }
522 522 }
523 523
524 524 /*
525 525 * Enter the s. file as a dependency for the
526 526 * plain file.
527 527 */
528 528 maybe_append_prop(plain_file, sccs_prop)->
529 529 body.sccs.file = file;
530 530 try_pattern:
531 531 MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2);
532 532 if ((pattern != NULL) &&
533 533 amatch(tmp_wcs_buffer, pattern)) {
534 534 if (debug_level > 0) {
535 535 WCSTOMBS(mbs_buffer, pattern);
536 536 (void) printf(gettext("'%s: %s' due to %s expansion\n"),
537 537 line->body.line.target->
538 538 string_mb,
539 539 plain_file->string_mb,
540 540 mbs_buffer);
541 541 }
542 542 enter_dependency(line, plain_file, false);
543 543 result++;
544 544 }
545 545 }
546 546 }
547 547 (void) closedir(dir_fd);
548 548
549 549 return result;
550 550 }
551 551
552 552 /*
553 553 * enter_file_name(name_string, library)
554 554 *
555 555 * Helper function for read_dir().
556 556 *
557 557 * Return value:
558 558 * The Name that was entered
559 559 *
560 560 * Parameters:
561 561 * name_string Name of the file we want to enter
562 562 * library The library it is a member of, if any
563 563 *
564 564 * Global variables used:
565 565 */
566 566 static Name
567 567 enter_file_name(wchar_t *name_string, wchar_t *library)
568 568 {
569 569 wchar_t buffer[STRING_BUFFER_LENGTH];
570 570 String_rec lib_name;
571 571 Name name;
572 572 Property prop;
573 573
574 574 if (library == NULL) {
575 575 name = GETNAME(name_string, FIND_LENGTH);
576 576 name->stat.is_file = true;
577 577 return name;
578 578 }
579 579
580 580 INIT_STRING_FROM_STACK(lib_name, buffer);
581 581 append_string(library, &lib_name, FIND_LENGTH);
582 582 append_char((int) parenleft_char, &lib_name);
583 583 append_string(name_string, &lib_name, FIND_LENGTH);
584 584 append_char((int) parenright_char, &lib_name);
585 585
586 586 name = GETNAME(lib_name.buffer.start, FIND_LENGTH);
587 587 name->stat.is_file = true;
588 588 name->is_member = true;
589 589 prop = maybe_append_prop(name, member_prop);
590 590 prop->body.member.library = GETNAME(library, FIND_LENGTH);
591 591 prop->body.member.library->stat.is_file = true;
592 592 prop->body.member.entry = NULL;
593 593 prop->body.member.member = GETNAME(name_string, FIND_LENGTH);
594 594 prop->body.member.member->stat.is_file = true;
595 595 return name;
596 596 }
597 597
598 598 /*
599 599 * star_match(string, pattern)
600 600 *
601 601 * This is a regular shell type wildcard pattern matcher
602 602 * It is used when xpanding wildcards in dependency lists
603 603 *
604 604 * Return value:
605 605 * Indication if the string matched the pattern
606 606 *
607 607 * Parameters:
608 608 * string String to match
609 609 * pattern Pattern to match it against
610 610 *
611 611 * Global variables used:
612 612 */
613 613 static Boolean
614 614 star_match(register wchar_t *string, register wchar_t *pattern)
615 615 {
616 616 register int pattern_ch;
617 617
618 618 switch (*pattern) {
619 619 case 0:
620 620 return succeeded;
621 621 case bracketleft_char:
622 622 case question_char:
623 623 case asterisk_char:
624 624 while (*string) {
625 625 if (amatch(string++, pattern)) {
626 626 return succeeded;
627 627 }
628 628 }
629 629 break;
630 630 default:
631 631 pattern_ch = (int) *pattern++;
632 632 while (*string) {
633 633 if ((*string++ == pattern_ch) &&
634 634 amatch(string, pattern)) {
635 635 return succeeded;
636 636 }
637 637 }
638 638 break;
639 639 }
640 640 return failed;
641 641 }
642 642
643 643 /*
644 644 * amatch(string, pattern)
645 645 *
646 646 * Helper function for shell pattern matching
647 647 *
648 648 * Return value:
649 649 * Indication if the string matched the pattern
650 650 *
651 651 * Parameters:
652 652 * string String to match
653 653 * pattern Pattern to match it against
654 654 *
655 655 * Global variables used:
656 656 */
657 657 static Boolean
658 658 amatch(register wchar_t *string, register wchar_t *pattern)
659 659 {
660 660 register long lower_bound;
661 661 register long string_ch;
662 662 register long pattern_ch;
663 663 register int k;
664 664
665 665 top:
666 666 for (; 1; pattern++, string++) {
667 667 lower_bound = 017777777777;
668 668 string_ch = *string;
669 669 switch (pattern_ch = *pattern) {
670 670 case bracketleft_char:
671 671 k = 0;
672 672 while ((pattern_ch = *++pattern) != 0) {
673 673 switch (pattern_ch) {
674 674 case bracketright_char:
675 675 if (!k) {
676 676 return failed;
677 677 }
678 678 string++;
679 679 pattern++;
680 680 goto top;
681 681 case hyphen_char:
682 682 k |= (lower_bound <= string_ch) &&
683 683 (string_ch <=
684 684 (pattern_ch = pattern[1]));
685 685 default:
686 686 if (string_ch ==
687 687 (lower_bound = pattern_ch)) {
688 688 k++;
689 689 }
690 690 }
691 691 }
692 692 return failed;
693 693 case asterisk_char:
694 694 return star_match(string, ++pattern);
695 695 case 0:
696 696 return BOOLEAN(!string_ch);
697 697 case question_char:
698 698 if (string_ch == 0) {
699 699 return failed;
700 700 }
701 701 break;
702 702 default:
703 703 if (pattern_ch != string_ch) {
704 704 return failed;
705 705 }
706 706 break;
707 707 }
708 708 }
709 709 /* NOTREACHED */
710 710 }
711 711
↓ open down ↓ |
191 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX