#include "shellexp.h"

using namespace std;

/* this was a C++ wrapper around C shellexpt() as
   a failed attempt to be more performant

   maybe the whole thing can now be ripped out
   and replace by a simplified "Non-recursive gitignore-style glob Matching"
   algorithm as seen here.

   https://www.codeproject.com/Articles/5163931/Fast-String-Matching-with-Wildcards-Globs-and-Giti

   --> CPOL is not DFSG compliant

   We do not want to support the "[...]" regexp, only
   the usual '?', '*' and the special '**'.

   For now cruft/cruft-ng expect that a glob pattern from the ruleset
   never ends with '/', so to declare a whole subdirecoty structure
   one has to list:
   - /var/spool/foo
   - /var/spool/foo/ **
   There's even a check in Makefile to ensure this rule is followed.

   This rule could be reversed, so that 'xxxxx/' is a dir, and 'xxxxx' is a file.
   This would make the .postrm snippets generated by 'dh-cruft'
   more accurate:
   - 'rm -f' for files
   - 'rm -rf' for dirs


   Morevover, the only case were '**' is not at the end of the file
   is Emacs, which I don't personally use,
   but looks like support for it could be added to python.cc

   tchet@brix ~/git/cruft-ng $ grep '\*\*' rules/ * | grep -v '\*\*$'
   rules/xemacs21:/usr/share/xemacs21/site-lisp/ ** / *.elc

   So support for '**' could be dropped altogether.
   (and this is only possible now because cruft-common is gone)
*/


/* error: ‘bool myglob(const std::string&, const std::string&)’
   was declared ‘extern’ and later ‘static’
*/
bool myglob(const string& file, const string& glob )
{
	bool result=shellexp(file.c_str(), glob.c_str());
	return result;
}

/* this is the original function from original "cruft" project */

/* 0 on no match, non-zero on match */
int shellexp(const char* string_, const char* pattern ) {
    /*  printf( "...matching( \"%s\", \"%s\" )\n", string_, pattern ); */

    switch( pattern[0] ) {
    case '\0':
	return string_[0] == '\0';
    case '?':
	switch( string_[0] ) {
	case '\0':
	case '/':
	    return false;
	default:
	    return shellexp( string_+1, pattern+1 );
	}
    case '/':
	if ( pattern[1] == '*' && pattern[2] == '*' ) {
	    const char* pch = string_;
	    if ( pattern[3] != '/' && pattern[3] != '\0' ) {
		fprintf( stderr, "Bad expression.\n" );
		return -1;
	    }
	    if ( *pch != '/' ) return false;
	    if ( pattern[3] == '\0' ) return true;
	    while ( *pch != '\0' ) {
		if ( *pch == '/' ) {
		    int ret = shellexp( pch, pattern + 3 );
		    if ( ret == true || ret == -1 )
		    	return ret;
		}
		pch++;
	    }
	    return false;
	} else if ( string_[0] == '/' ) {
		return shellexp( string_+1, pattern+1 );
	} else
		return false;
    case '*':
	if ( string_[0] == '/' ) return shellexp( string_, pattern+1 );
	{
		int ret = shellexp( string_, pattern+1 );
		if (ret == false)
			return string_[0] != '\0' ? shellexp( string_ + 1, pattern ) : false;
		else
			return ret;
	}
    default:
	if (pattern[0] != string_[0])
		return false;
	else
		return shellexp( string_ + 1, pattern + 1 );
    }
}

