Linux debugging

Check our new training course

Linux debugging, tracing, profiling & perf. analysis

Check our new training course
with Creative Commons CC-BY-SA
lecture and lab materials

Bootlin logo

Elixir Cross Referencer

/*
 * ##/%% variable matching code ripped out of ash shell for code sharing
 *
 * Copyright (c) 1989, 1991, 1993, 1994
 *      The Regents of the University of California.  All rights reserved.
 *
 * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
 * was re-ported from NetBSD and debianized.
 *
 * This code is derived from software contributed to Berkeley by
 * Kenneth Almquist.
 *
 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
 *
 * Original BSD copyright notice is retained at the end of this file.
 */
#ifdef STANDALONE
# include <stdbool.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <unistd.h>
#else
# include "libbb.h"
#endif
#include <fnmatch.h>
#include "match.h"

#define pmatch(a, b) !fnmatch((a), (b), 0)

char *scanleft(char *string, char *pattern, bool zero)
{
	char c;
	char *loc = string;

	do {
		int match;
		const char *s;

		c = *loc;
		if (zero) {
			*loc = '\0';
			s = string;
		} else
			s = loc;
		match = pmatch(pattern, s);
		*loc = c;

		if (match)
			return loc;

		loc++;
	} while (c);

	return NULL;
}

char *scanright(char *string, char *pattern, bool zero)
{
	char c;
	char *loc = string + strlen(string);

	while (loc >= string) {
		int match;
		const char *s;

		c = *loc;
		if (zero) {
			*loc = '\0';
			s = string;
		} else
			s = loc;
		match = pmatch(pattern, s);
		*loc = c;

		if (match)
			return loc;

		loc--;
	}

	return NULL;
}

#ifdef STANDALONE
int main(int argc, char *argv[])
{
	char *string;
	char *op;
	char *pattern;
	bool zero;
	char *loc;

	int i;

	if (argc == 1) {
		puts(
			"Usage: match <test> [test...]\n\n"
			"Where a <test> is the form: <string><op><match>\n"
			"This is to test the shell ${var#val} expression type.\n\n"
			"e.g. `match 'abc#a*'` -> bc"
		);
		return 1;
	}

	for (i = 1; i < argc; ++i) {
		size_t off;
		scan_t scan;

		printf("'%s': ", argv[i]);

		string = strdup(argv[i]);
		off = strcspn(string, "#%");
		if (!off) {
			printf("invalid format\n");
			free(string);
			continue;
		}
		op = string + off;
		scan = pick_scan(op[0], op[1], &zero);
		pattern = op + 1;
		if (op[0] == op[1])
			op[1] = '\0', ++pattern;
		op[0] = '\0';

		loc = scan(string, pattern, zero);

		if (zero) {
			printf("'%s'\n", loc);
		} else {
			*loc = '\0';
			printf("'%s'\n", string);
		}

		free(string);
	}

	return 0;
}
#endif