From 985e187fdbd1d9331c87118f863d7e69e578f6a8 Mon Sep 17 00:00:00 2001 From: Kaipeng Zeng Date: Sun, 19 Apr 2015 10:40:11 +0800 Subject: [PATCH 2/2] findstr: Added initial implementation. --- programs/findstr/Makefile.in | 2 +- programs/findstr/findstr.h | 26 ++++++++ programs/findstr/main.c | 137 ++++++++++++++++++++++++++++++++++++--- programs/findstr/tests/findstr.c | 20 +++--- 4 files changed, 166 insertions(+), 19 deletions(-) create mode 100644 programs/findstr/findstr.h diff --git a/programs/findstr/Makefile.in b/programs/findstr/Makefile.in index 10875af..a919538 100644 --- a/programs/findstr/Makefile.in +++ b/programs/findstr/Makefile.in @@ -1,5 +1,5 @@ MODULE = findstr.exe -APPMODE = -mconsole -municode +APPMODE = -mconsole -municode -mno-cygwin C_SRCS = \ main.c diff --git a/programs/findstr/findstr.h b/programs/findstr/findstr.h new file mode 100644 index 0000000..0f0289b --- /dev/null +++ b/programs/findstr/findstr.h @@ -0,0 +1,26 @@ +#include + +#define OPT_B 0x00000001 +#define OPT_E 0x00000002 +#define OPT_L 0x00000004 +#define OPT_R 0x00000008 +#define OPT_P 0x00000010 +#define OPT_S 0x00000020 +#define OPT_I 0x00000040 +#define OPT_X 0x00000080 +#define OPT_V 0x00000100 +#define OPT_N 0x00000200 +#define OPT_M 0x00000400 +#define OPT_O 0x00000800 +#define OPT_OF 0x00001000 +#define OPT_A 0x00002000 +#define OPT_DEFAULT 0x00004000 + +#define MAXSTRING 8192 + +typedef struct { + LPWSTR words; + LPWSTR *files; + LONG file_count; + DWORD flags; +} findstr_cmd; diff --git a/programs/findstr/main.c b/programs/findstr/main.c index de5de33..af0af18 100644 --- a/programs/findstr/main.c +++ b/programs/findstr/main.c @@ -1,5 +1,6 @@ /* * Copyright 2012 Qian Hong + * Copyright 2015 Kaipeng Zeng * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,18 +17,138 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "wine/debug.h" +#include +#include +#include +#include +#include +#include "findstr.h" WINE_DEFAULT_DEBUG_CHANNEL(findstr); -int wmain(int argc, WCHAR *argv[]) + +static int findstr_wprintf(const WCHAR *format, ...) +{ + static char output_bufA[65536]; + static WCHAR output_bufW[sizeof(output_bufA) / sizeof(WCHAR)]; + va_list parms; + DWORD nOut; + BOOL res = FALSE; + HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE); + + va_start(parms, format); + vsnprintfW(output_bufW, sizeof(output_bufW), format, parms); + va_end(parms); + + /* Try to write as unicode whenever we think it's a console */ + if(((DWORD_PTR)hout & 3) == 3) + { + res = WriteConsoleW(hout, output_bufW, strlenW(output_bufW), &nOut, NULL); + } + else + { + DWORD convertedChars; + + /* Convert to OEM, then output */ + convertedChars = WideCharToMultiByte(GetConsoleOutputCP(), 0, output_bufW, -1, + output_bufA, sizeof(output_bufA), + NULL, NULL); + res = WriteFile(hout, output_bufA, convertedChars, &nOut, FALSE); + } + + return res ? nOut : 0; +} + +int match_pattern(findstr_cmd cmd) { - int i; + FILE *read_file; + WCHAR line[MAXSTRING] = {0}; + int i = 0,ret = 1; + WCHAR readTextMode[] = {'r','t',0}; + WCHAR fileNoExistErr[] = {'C', 'a', 'n', '\'', 't', ' ', 'f', 'i', 'n', 'd', ' ', + 'f', 'i', 'l', 'e', ' ', ':', ' ', 0}; + WCHAR newline[] = {'\n', 0}; + WCHAR *output; - WINE_FIXME("stub:"); - for (i = 0; i < argc; i++) - WINE_FIXME(" %s", wine_dbgstr_w(argv[i])); - WINE_FIXME("\n"); + output = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 65535); + for(i = 0; i < cmd.file_count; i++) + { + if(!(read_file = _wfopen(cmd.files[i], readTextMode))) + { + lstrcatW(output, fileNoExistErr); + lstrcatW(output, cmd.files[i]); + lstrcatW(output, newline); + continue; + } + while(fgetws(line, MAXSTRING, read_file ) != NULL) + { + if(wcsstr(line, cmd.words) != NULL) + { + TRACE("%s\n", debugstr_w(line)); + lstrcatW(output, line); + ret = 0; + } + } + } + findstr_wprintf(output); + HeapFree(GetProcessHeap(), 0, output); + return ret; +} + +static findstr_cmd parse_cmd(int argc, WCHAR *argv[]) +{ + int i, j; + findstr_cmd cmd; + + cmd.flags = OPT_DEFAULT; + cmd.words = NULL; + cmd.files = NULL; + cmd.file_count = argc - 1; + + for(i = 1; i < argc; i++) + { + if(argv[i][0] == '/') + { + cmd.file_count--; + for(j = 1; j < lstrlenW(argv[i]); j++) + { + switch(argv[i][j]) + { + case 'B':case 'b': cmd.flags |= OPT_B; break; + case 'E':case 'e': cmd.flags |= OPT_E; break; + case 'L':case 'l': cmd.flags |= OPT_L; break; + case 'R':case 'r': cmd.flags |= OPT_R; break; + case 'P':case 'p': cmd.flags |= OPT_P; break; + case 'S':case 's': cmd.flags |= OPT_S; break; + case 'I':case 'i': cmd.flags |= OPT_I; break; + case 'X':case 'x': cmd.flags |= OPT_X; break; + case 'V':case 'v': cmd.flags |= OPT_V; break; + case 'N':case 'n': cmd.flags |= OPT_N; break; + case 'M':case 'm': cmd.flags |= OPT_M; break; + case 'O':case 'o': cmd.flags |= OPT_O; break; + case 'A':case 'a': cmd.flags |= OPT_A; break; + } + } + } + else if(!cmd.words) + { + cmd.file_count--; + cmd.words = &argv[i][0]; + } + else if(!cmd.files) + cmd.files = &argv[i]; + } + TRACE("Option flags is 0x%08x, words: %s, intput files: ", cmd.flags, debugstr_w(cmd.words)); + for(i = 0; i < cmd.file_count; i++) + TRACE("%s ", debugstr_w(cmd.files[i])); + TRACE("\n"); + return cmd; +} + +int wmain(int argc, WCHAR *argv[]) +{ + findstr_cmd cmd; - return 0; + cmd = parse_cmd(argc, &argv[0]); + return match_pattern(cmd); } diff --git a/programs/findstr/tests/findstr.c b/programs/findstr/tests/findstr.c index 705fd89..2b46d14 100644 --- a/programs/findstr/tests/findstr.c +++ b/programs/findstr/tests/findstr.c @@ -121,36 +121,36 @@ static void test_without_arg(void) cmdline = generate_cmdline("free", filename); res = runcmd(cmdline, &buffer); - todo_wine ok(!res, "Return %d expected 0.\n", res); - todo_wine ok(!strcmp(buffer, "Wine will always be free software.\n"), + ok(!res, "Return %d expected 0.\n", res); + ok(!strcmp(buffer, "Wine will always be free software.\n"), "Return wrong string: %s.\n", buffer); cleanup(&buffer, &cmdline); cmdline = generate_cmdline("", filename); res = runcmd(cmdline, &buffer); - todo_wine ok(res == 1, "Return %d expected 1.\n", res); - todo_wine ok(!strcmp(buffer, ""), + ok(res == 1, "Return %d expected 1.\n", res); + ok(!strcmp(buffer, ""), "Return wrong string: %s.\n", buffer); cleanup(&buffer, &cmdline); cmdline = generate_cmdline("Free", filename); res = runcmd(cmdline, &buffer); - todo_wine ok(res == 1, "Return %d expected 1.\n", res); - todo_wine ok(!strcmp(buffer, ""), + ok(res == 1, "Return %d expected 1.\n", res); + ok(!strcmp(buffer, ""), "Return wrong string: %s.\n", buffer); cleanup(&buffer, &cmdline); cmdline = generate_cmdline("omg", filename); res = runcmd(cmdline, &buffer); - todo_wine ok(res == 1, "Return %d expected 1.\n", res); - todo_wine ok(!strcmp(buffer, ""), + ok(res == 1, "Return %d expected 1.\n", res); + ok(!strcmp(buffer, ""), "Return wrong string: %s.\n", buffer); cleanup(&buffer, &cmdline); cmdline = generate_cmdline("Wine", filename); res = runcmd(cmdline, &buffer); - todo_wine ok(!res, "Return %d expected 0.\n", res); - todo_wine ok(!strcmp(buffer, "Wine Is Not an Emulator.\nWine will always be free software.\n" + ok(!res, "Return %d expected 0.\n", res); + ok(!strcmp(buffer, "Wine Is Not an Emulator.\nWine will always be free software.\n" "Wine is heavily reliant on its user community too."), "Return wrong string: %s.\n", buffer); cleanup(&buffer, &cmdline); -- 2.1.0