hush: fix handling of backslashes in variable assignment
[oweals/busybox.git] / shell / match.c
1 /*
2  * ##/%% variable matching code ripped out of ash shell for code sharing
3  *
4  * This code is derived from software contributed to Berkeley by
5  * Kenneth Almquist.
6  *
7  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8  *
9  * Copyright (c) 1989, 1991, 1993, 1994
10  *      The Regents of the University of California.  All rights reserved.
11  *
12  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
13  * was re-ported from NetBSD and debianized.
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 #else
22 # include "libbb.h"
23 #endif
24 #include <fnmatch.h>
25 #include "match.h"
26
27 #define pmatch(a, b) !fnmatch((a), (b), 0)
28
29 char *scanleft(char *string, char *pattern, bool match_at_left)
30 {
31         char c;
32         char *loc = string;
33
34         while (1) {
35                 int match;
36
37                 c = *loc;
38                 if (match_at_left) {
39                         *loc = '\0';
40                         match = pmatch(pattern, string);
41                         *loc = c;
42                 } else {
43                         match = pmatch(pattern, loc);
44                 }
45                 if (match)
46                         return loc;
47                 if (!c)
48                         return NULL;
49                 loc++;
50         }
51 }
52
53 char *scanright(char *string, char *pattern, bool match_at_left)
54 {
55         char c;
56         char *loc = string + strlen(string);
57
58         while (loc >= string) {
59                 int match;
60
61                 c = *loc;
62                 if (match_at_left) {
63                         *loc = '\0';
64                         match = pmatch(pattern, string);
65                         *loc = c;
66                 } else {
67                         match = pmatch(pattern, loc);
68                 }
69                 if (match)
70                         return loc;
71                 loc--;
72         }
73
74         return NULL;
75 }
76
77 #ifdef STANDALONE
78 int main(int argc, char *argv[])
79 {
80         char *string;
81         char *op;
82         char *pattern;
83         bool match_at_left;
84         char *loc;
85
86         int i;
87
88         if (argc == 1) {
89                 puts(
90                         "Usage: match <test> [test...]\n\n"
91                         "Where a <test> is the form: <string><op><match>\n"
92                         "This is to test the shell ${var#val} expression type.\n\n"
93                         "e.g. `match 'abc#a*'` -> bc"
94                 );
95                 return 1;
96         }
97
98         for (i = 1; i < argc; ++i) {
99                 size_t off;
100                 scan_t scan;
101
102                 printf("'%s': ", argv[i]);
103
104                 string = strdup(argv[i]);
105                 off = strcspn(string, "#%");
106                 if (!off) {
107                         printf("invalid format\n");
108                         free(string);
109                         continue;
110                 }
111                 op = string + off;
112                 scan = pick_scan(op[0], op[1], &match_at_left);
113                 pattern = op + 1;
114                 if (op[0] == op[1])
115                         op[1] = '\0', ++pattern;
116                 op[0] = '\0';
117
118                 loc = scan(string, pattern, match_at_left);
119
120                 if (match_at_left) {
121                         printf("'%s'\n", loc);
122                 } else {
123                         *loc = '\0';
124                         printf("'%s'\n", string);
125                 }
126
127                 free(string);
128         }
129
130         return 0;
131 }
132 #endif