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