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
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
];
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
);
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
;
54 ptr
= &((*ptr
)->next
);
56 new_file
= calloc(1, sizeof(*new_file
));
59 WINE_ERR("Out of memory.\n");
65 new_file
->file
= stdin
;
69 new_file
->file
= _wfopen(path
, L
"rt,ccs=unicode");
72 findstr_error_wprintf(STRING_CANNOT_OPEN
, path
);
81 static void add_string(struct findstr_string
**head
, const WCHAR
*string
)
83 struct findstr_string
**ptr
, *new_string
;
87 ptr
= &((*ptr
)->next
);
89 new_string
= calloc(1, sizeof(*new_string
));
92 WINE_ERR("Out of memory.\n");
96 new_string
->string
= 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
;
108 for (i
= 0; i
< argc
; i
++)
109 WINE_TRACE("%s ", wine_dbgstr_w(argv
[i
]));
114 findstr_error_wprintf(STRING_BAD_COMMAND_LINE
);
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
);
129 while (argv
[i
][j
] != '\0')
134 findstr_message(STRING_USAGE
);
139 if (argv
[i
][j
+ 1] == ':')
141 ptr
= argv
[i
] + j
+ 2;
146 while (*ptr
!= '"' && *ptr
!= '\0' )
149 j
= ptr
- argv
[i
] - 1;
150 add_string(&string_head
, string
);
155 findstr_error_wprintf(STRING_IGNORED
, argv
[i
][j
]);
162 else if (!has_string
)
164 string
= wcstok(argv
[i
], L
" ", &buffer
);
167 add_string(&string_head
, string
);
170 while ((string
= wcstok(NULL
, L
" ", &buffer
)))
171 add_string(&string_head
, string
);
175 if (!add_file(&file_head
, argv
[i
]))
183 findstr_error_wprintf(STRING_BAD_COMMAND_LINE
);
189 add_file(&file_head
, NULL
);
191 current_file
= file_head
;
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
))
202 if (current_file
->file
== stdin
)
207 current_string
= current_string
->next
;
211 current_file
= current_file
->next
;
215 current_file
= file_head
;
218 next_file
= current_file
->next
;
219 if (current_file
->file
!= stdin
)
220 fclose(current_file
->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
;