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