1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#ifdef STANDALONE
16# include <stdbool.h>
17# include <stdio.h>
18# include <stdlib.h>
19# include <string.h>
20# include <unistd.h>
21# define FAST_FUNC
22# define PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
23# define POP_SAVED_FUNCTION_VISIBILITY
24#else
25# include "libbb.h"
26#endif
27#include <fnmatch.h>
28#include "match.h"
29
30char* FAST_FUNC scan_and_match(char *string, const char *pattern, unsigned flags)
31{
32 char *loc;
33 char *end;
34 unsigned len = strlen(string);
35 int early_exit;
36
37
38
39
40
41
42
43
44 early_exit = (flags == (SCAN_MOVE_FROM_LEFT + SCAN_MATCH_RIGHT_HALF) && pattern[0] == '*');
45
46 if (flags & SCAN_MOVE_FROM_LEFT) {
47 loc = string;
48 end = string + len + 1;
49 } else {
50 loc = string + len;
51 end = string - 1;
52 if (flags == (SCAN_MOVE_FROM_RIGHT + SCAN_MATCH_LEFT_HALF)) {
53
54
55
56
57 const char *p = pattern + strlen(pattern);
58 if (--p >= pattern && *p == '*') {
59 early_exit = 1;
60 while (--p >= pattern && *p == '\\')
61 early_exit ^= 1;
62 }
63 }
64 }
65
66 while (loc != end) {
67 char c;
68 int r;
69
70 c = *loc;
71 if (flags & SCAN_MATCH_LEFT_HALF) {
72 *loc = '\0';
73 r = fnmatch(pattern, string, 0);
74
75 *loc = c;
76 } else {
77 r = fnmatch(pattern, loc, 0);
78
79 }
80 if (r == 0)
81 return loc;
82 if (early_exit) {
83#ifdef STANDALONE
84 printf("(early exit) ");
85#endif
86 break;
87 }
88
89 if (flags & SCAN_MOVE_FROM_LEFT) {
90 loc++;
91 } else {
92 loc--;
93 }
94 }
95 return NULL;
96}
97
98#ifdef STANDALONE
99int main(int argc, char *argv[])
100{
101 char *string;
102 char *op;
103 char *pattern;
104 char *loc;
105
106 setvbuf(stdout, NULL, _IONBF, 0);
107
108 if (!argv[1]) {
109 puts(
110 "Usage: match <test> [test...]\n\n"
111 "Where a <test> is the form: <string><op><match>\n"
112 "This is to test the shell ${var#val} expression type.\n\n"
113 "e.g. `match 'abc#a*'` -> bc"
114 );
115 return 1;
116 }
117
118 while (*++argv) {
119 size_t off;
120 unsigned scan_flags;
121
122 string = *argv;
123 off = strcspn(string, "#%");
124 if (!off) {
125 printf("invalid format\n");
126 continue;
127 }
128 op = string + off;
129 scan_flags = pick_scan(op[0], op[1]);
130
131 printf("'%s': flags:%x, ", string, scan_flags);
132 pattern = op + 1;
133 if (op[0] == op[1])
134 pattern++;
135 op[0] = '\0';
136
137 loc = scan_and_match(string, pattern, scan_flags);
138
139 if (scan_flags & SCAN_MATCH_LEFT_HALF) {
140 printf("'%s'\n", loc);
141 } else {
142 if (loc)
143 *loc = '\0';
144 printf("'%s'\n", string);
145 }
146 }
147
148 return 0;
149}
150#endif
151