#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <cctype>

using namespace std;

struct flags_t
{
    flags_t() : iflag(false), vflag(false), xflag(false) {}
    bool iflag;
    bool vflag;
    bool xflag;
};

void print_usage();
void args( int argc, char *argv[], flags_t& flgs, vector<string>& pars);
void flags( char *arg, flags_t& flgs);
void gloop( flags_t flgs, vector<string> pars);
void grep( string prefix, string ptrn, istream& inp, flags_t flgs);
bool match( string line, string ptrn, flags_t flgs);

int retval = 1;

int main( int argc, char *argv[])
{
    flags_t flgs;
    vector<string> pars;

    args( argc, argv, flgs, pars);
    gloop( flgs, pars);

    return retval;
}

void args( int argc, char *argv[], flags_t& flgs, vector<string>& pars)
{
    for ( int i = 1; i < argc; ++i )
    {
        if ( '-' == argv[i][0] )
            flags( argv[i], flgs);
        else
            pars.push_back(argv[i]);
    }
    if ( 0 == pars.size() )
    {
        // nincsen minta: abort
        print_usage();
    }
}

// nincsen lekezelve: grep -
void flags( char *arg, flags_t& flgs)
{
    for ( int j = 1; '\0' != arg[j]; ++j )
    {
       switch ( arg[j] )
       {
       default : print_usage();     break;
       case 'i': flgs.iflag = true; break;
       case 'v': flgs.vflag = true; break;
       case 'x': flgs.xflag = true; break;
       }
    }
}

void print_usage()
{
    cerr << "Usage: grep [OPTION]... PATTERN [FILE]..." << endl;
    exit(2);
}

void gloop( flags_t flgs, vector<string> pars)
{
    if ( 1 == pars.size() )
        grep( "", pars[0], cin, flgs);
    else
        for ( size_t i = 1; i < pars.size(); ++i )
        {
            ifstream inp( pars[i].c_str());

            if ( inp )
                grep( pars.size()>2?pars[i]+":":"", pars[0], inp, flgs);
            else
            {
                cerr << pars[i] << ": cannot open file" << endl;
                retval = 2;
            }
        }
}

void grep( string prefix, string ptrn, istream& inp, flags_t flgs)
{
    string line;

    while ( getline( inp, line) )
    {
        if ( match( line, ptrn, flgs ) )
        {
            cout << prefix << line << endl;
            retval = (2 == retval) ? 2 : 0;
        }
    }
}

bool match( string line, string ptrn, flags_t flgs)
{
    bool ismatch = false;

    if ( flgs.iflag )
    {
        for (size_t i = 0; i < line.size(); ++i ) line[i] = toupper(line[i]);
        for (size_t i = 0; i < ptrn.size(); ++i ) ptrn[i] = toupper(ptrn[i]);
    }

    if ( flgs.xflag )
        ismatch =  line == ptrn;
    else
        ismatch =  line.find(ptrn) != line.npos;

    if ( flgs.vflag )
        ismatch = ! ismatch;

    return ismatch;
}