dmime: Fix performance message requeue-ing from the message thread.
[wine.git] / programs / findstr / main.c
blob3a6a250f514322593024cc5df9961fec62756c56
1 /*
2 * Copyright 2012 Qian Hong
3 * Copyright 2023 Zhiyi Zhang for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <windows.h>
21 #include <stdio.h>
22 #include "findstr.h"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(findstr);
27 static int WINAPIV findstr_error_wprintf(int msg, ...)
29 WCHAR msg_buffer[MAXSTRING];
30 va_list va_args;
31 int ret;
33 LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer));
34 va_start(va_args, msg);
35 ret = vfwprintf(stderr, msg_buffer, va_args);
36 va_end(va_args);
37 return ret;
40 static int findstr_message(int msg)
42 WCHAR msg_buffer[MAXSTRING];
44 LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer));
45 return wprintf(msg_buffer);
48 static BOOL add_file(struct findstr_file **head, const WCHAR *path)
50 struct findstr_file **ptr, *new_file;
52 ptr = head;
53 while (*ptr)
54 ptr = &((*ptr)->next);
56 new_file = calloc(1, sizeof(*new_file));
57 if (!new_file)
59 WINE_ERR("Out of memory.\n");
60 return FALSE;
63 if (!path)
65 new_file->file = stdin;
67 else
69 new_file->file = _wfopen(path, L"rt,ccs=unicode");
70 if (!new_file->file)
72 findstr_error_wprintf(STRING_CANNOT_OPEN, path);
73 return FALSE;
77 *ptr = new_file;
78 return TRUE;
81 static void add_string(struct findstr_string **head, const WCHAR *string)
83 struct findstr_string **ptr, *new_string;
85 ptr = head;
86 while (*ptr)
87 ptr = &((*ptr)->next);
89 new_string = calloc(1, sizeof(*new_string));
90 if (!new_string)
92 WINE_ERR("Out of memory.\n");
93 return;
96 new_string->string = string;
97 *ptr = new_string;
100 int __cdecl wmain(int argc, WCHAR *argv[])
102 struct findstr_string *string_head = NULL, *current_string, *next_string;
103 struct findstr_file *file_head = NULL, *current_file, *next_file;
104 WCHAR *string, *ptr, *buffer, line[MAXSTRING];
105 BOOL has_string = FALSE, has_file = FALSE;
106 int ret = 1, i, j;
108 for (i = 0; i < argc; i++)
109 WINE_TRACE("%s ", wine_dbgstr_w(argv[i]));
110 WINE_TRACE("\n");
112 if (argc == 1)
114 findstr_error_wprintf(STRING_BAD_COMMAND_LINE);
115 return 2;
118 for (i = 1; i < argc; i++)
120 if (argv[i][0] == '/')
122 if (argv[i][1] == '\0')
124 findstr_error_wprintf(STRING_BAD_COMMAND_LINE);
125 return 2;
128 j = 1;
129 while (argv[i][j] != '\0')
131 switch(argv[i][j])
133 case '?':
134 findstr_message(STRING_USAGE);
135 ret = 0;
136 goto done;
137 case 'C':
138 case 'c':
139 if (argv[i][j + 1] == ':')
141 ptr = argv[i] + j + 2;
142 if (*ptr == '"')
143 ptr++;
145 string = ptr;
146 while (*ptr != '"' && *ptr != '\0' )
147 ptr++;
148 *ptr = '\0';
149 j = ptr - argv[i] - 1;
150 add_string(&string_head, string);
151 has_string = TRUE;
153 break;
154 default:
155 findstr_error_wprintf(STRING_IGNORED, argv[i][j]);
156 break;
159 j++;
162 else if (!has_string)
164 string = wcstok(argv[i], L" ", &buffer);
165 if (string)
167 add_string(&string_head, string);
168 has_string = TRUE;
170 while ((string = wcstok(NULL, L" ", &buffer)))
171 add_string(&string_head, string);
173 else
175 if (!add_file(&file_head, argv[i]))
176 goto done;
177 has_file = TRUE;
181 if (!has_string)
183 findstr_error_wprintf(STRING_BAD_COMMAND_LINE);
184 ret = 2;
185 goto done;
188 if (!has_file)
189 add_file(&file_head, NULL);
191 current_file = file_head;
192 while (current_file)
194 while (fgetws(line, ARRAY_SIZE(line), current_file->file))
196 current_string = string_head;
197 while (current_string)
199 if (wcsstr(line, current_string->string))
201 wprintf(line);
202 if (current_file->file == stdin)
203 wprintf(L"\n");
204 ret = 0;
207 current_string = current_string->next;
211 current_file = current_file->next;
214 done:
215 current_file = file_head;
216 while (current_file)
218 next_file = current_file->next;
219 if (current_file->file != stdin)
220 fclose(current_file->file);
221 free(current_file);
222 current_file = next_file;
225 current_string = string_head;
226 while (current_string)
228 next_string = current_string->next;
229 free(current_string);
230 current_string = next_string;
232 return ret;