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 the GPL v2 or later, see the file LICENSE in this tarball.
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
29char *scanleft(char *string, char *pattern, bool match_at_left)
30{
31	char c;
32	char *loc = string;
33
34	do {
35		int match;
36		const char *s;
37
38		c = *loc;
39		if (match_at_left) {
40			*loc = '\0';
41			s = string;
42		} else
43			s = loc;
44		match = pmatch(pattern, s);
45		*loc = c;
46
47		if (match)
48			return loc;
49
50		loc++;
51	} while (c);
52
53	return NULL;
54}
55
56char *scanright(char *string, char *pattern, bool match_at_left)
57{
58	char c;
59	char *loc = string + strlen(string);
60
61	while (loc >= string) {
62		int match;
63		const char *s;
64
65		c = *loc;
66		if (match_at_left) {
67			*loc = '\0';
68			s = string;
69		} else
70			s = loc;
71		match = pmatch(pattern, s);
72		*loc = c;
73
74		if (match)
75			return loc;
76
77		loc--;
78	}
79
80	return NULL;
81}
82
83#ifdef STANDALONE
84int main(int argc, char *argv[])
85{
86	char *string;
87	char *op;
88	char *pattern;
89	bool match_at_left;
90	char *loc;
91
92	int i;
93
94	if (argc == 1) {
95		puts(
96			"Usage: match <test> [test...]\n\n"
97			"Where a <test> is the form: <string><op><match>\n"
98			"This is to test the shell ${var#val} expression type.\n\n"
99			"e.g. `match 'abc#a*'` -> bc"
100		);
101		return 1;
102	}
103
104	for (i = 1; i < argc; ++i) {
105		size_t off;
106		scan_t scan;
107
108		printf("'%s': ", argv[i]);
109
110		string = strdup(argv[i]);
111		off = strcspn(string, "#%");
112		if (!off) {
113			printf("invalid format\n");
114			free(string);
115			continue;
116		}
117		op = string + off;
118		scan = pick_scan(op[0], op[1], &match_at_left);
119		pattern = op + 1;
120		if (op[0] == op[1])
121			op[1] = '\0', ++pattern;
122		op[0] = '\0';
123
124		loc = scan(string, pattern, match_at_left);
125
126		if (match_at_left) {
127			printf("'%s'\n", loc);
128		} else {
129			*loc = '\0';
130			printf("'%s'\n", string);
131		}
132
133		free(string);
134	}
135
136	return 0;
137}
138#endif
139