1 /* $NetBSD: opattern.c,v 1.5 2009/02/02 12:35:01 joerg Exp $ */
10 __RCSID("$NetBSD: opattern.c,v 1.5 2009/02/02 12:35:01 joerg Exp $");
13 * FreeBSD install - a package for the installation and maintainance
14 * of non-core utilities.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
28 * Miscellaneous string utilities.
44 /* pull in definitions and macros for resizing arrays as we go */
48 * Perform alternate match on "pkg" against "pattern",
49 * calling pkg_match (recursively) to resolve any other patterns.
50 * Return 1 on match, 0 otherwise
53 alternate_match(const char *pattern
, const char *pkg
)
56 char buf
[MaxPathSize
];
63 if ((sep
= strchr(pattern
, '{')) == (char *) NULL
) {
64 errx(EXIT_FAILURE
, "alternate_match(): '{' expected in `%s'", pattern
);
66 (void) strncpy(buf
, pattern
, (size_t) (sep
- pattern
));
67 alt
= &buf
[sep
- pattern
];
69 for (cnt
= 0, cp
= sep
; *cp
&& last
== (char *) NULL
; cp
++) {
72 } else if (*cp
== '}' && --cnt
== 0 && last
== (char *) NULL
) {
77 errx(EXIT_FAILURE
, "Malformed alternate `%s'", pattern
);
79 for (found
= 0, cp
= sep
+ 1; *sep
!= '}'; cp
= sep
+ 1) {
80 for (cnt
= 0, sep
= cp
; cnt
> 0 || (cnt
== 0 && *sep
!= '}' && *sep
!= ','); sep
++) {
83 } else if (*sep
== '}') {
87 (void) snprintf(alt
, sizeof(buf
) - (alt
- buf
), "%.*s%s", (int) (sep
- cp
), cp
, last
);
88 if (pkg_match(buf
, pkg
) == 1) {
96 * Perform glob match on "pkg" against "pattern".
97 * Return 1 on match, 0 otherwise
100 glob_match(const char *pattern
, const char *pkg
)
102 return fnmatch(pattern
, pkg
, FNM_PERIOD
) == 0;
106 * Perform simple match on "pkg" against "pattern".
107 * Return 1 on match, 0 otherwise
110 simple_match(const char *pattern
, const char *pkg
)
112 return strcmp(pattern
, pkg
) == 0;
116 * Performs a fast check if pattern can ever match pkg.
117 * Returns 1 if a match is possible and 0 otherwise.
120 quick_pkg_match(const char *pattern
, const char *pkg
)
122 #define simple(x) (isalnum((unsigned char)(x)) || (x) == '-')
123 if (!simple(pattern
[0]))
125 if (pattern
[0] != pkg
[0])
128 if (!simple(pattern
[1]))
130 if (pattern
[1] != pkg
[1])
137 * Match pkg against pattern, return 1 if matching, 0 else
140 pkg_match(const char *pattern
, const char *pkg
)
142 if (!quick_pkg_match(pattern
, pkg
))
145 if (strchr(pattern
, '{') != (char *) NULL
) {
146 /* emulate csh-type alternates */
147 return alternate_match(pattern
, pkg
);
149 if (strpbrk(pattern
, "<>") != (char *) NULL
) {
152 /* perform relational dewey match on version number */
153 ret
= dewey_match(pattern
, pkg
);
155 errx(EXIT_FAILURE
, "dewey_match returned error");
158 if (strpbrk(pattern
, "*?[]") != (char *) NULL
) {
160 if (glob_match(pattern
, pkg
))
164 /* no alternate, dewey or glob match -> simple compare */
165 if (simple_match(pattern
, pkg
))
168 /* globbing patterns and simple matches may be specified with or
169 * without the version number, so check for both cases. */
175 pattern_ver
= xasprintf("%s-[0-9]*", pattern
);
176 retval
= glob_match(pattern_ver
, pkg
);
183 pkg_order(const char *pattern
, const char *first_pkg
, const char *second_pkg
)
185 const char *first_version
;
186 const char *second_version
;
188 if (first_pkg
== NULL
&& second_pkg
== NULL
)
191 if (first_pkg
== NULL
)
192 return pkg_match(pattern
, second_pkg
) ? 2 : 0;
193 if (second_pkg
== NULL
)
194 return pkg_match(pattern
, first_pkg
) ? 1 : 0;
196 first_version
= strrchr(first_pkg
, '-');
197 second_version
= strrchr(second_pkg
, '-');
199 if (first_version
== NULL
|| !pkg_match(pattern
, first_pkg
))
200 return pkg_match(pattern
, second_pkg
) ? 2 : 0;
202 if (second_version
== NULL
|| !pkg_match(pattern
, second_pkg
))
203 return pkg_match(pattern
, first_pkg
) ? 1 : 0;
205 if (dewey_cmp(first_version
+ 1, DEWEY_GT
, second_version
+ 1))